Repository: voideditor/void
Branch: main
Commit: 17e7a5b15243
Files: 8041
Total size: 103.7 MB
Directory structure:
gitextract_zxyiywqm/
├── .config/
│ ├── 1espt/
│ │ └── PipelineAutobaseliningConfig.yml
│ └── guardian/
│ ├── .gdnbaselines
│ └── .gdnsuppress
├── .configurations/
│ └── configuration.dsc.yaml
├── .devcontainer/
│ ├── Dockerfile
│ ├── README.md
│ ├── devcontainer-lock.json
│ ├── devcontainer.json
│ ├── install-vscode.sh
│ └── post-create.sh
├── .editorconfig
├── .eslint-ignore
├── .eslint-plugin-local/
│ ├── code-amd-node-module.ts
│ ├── code-declare-service-brand.ts
│ ├── code-ensure-no-disposables-leak-in-test.ts
│ ├── code-import-patterns.ts
│ ├── code-layering.ts
│ ├── code-limited-top-functions.ts
│ ├── code-must-use-result.ts
│ ├── code-must-use-super-dispose.ts
│ ├── code-no-dangerous-type-assertions.ts
│ ├── code-no-global-document-listener.ts
│ ├── code-no-native-private.ts
│ ├── code-no-nls-in-standalone-editor.ts
│ ├── code-no-potentially-unsafe-disposables.ts
│ ├── code-no-runtime-import.ts
│ ├── code-no-standalone-editor.ts
│ ├── code-no-static-self-ref.ts
│ ├── code-no-test-async-suite.ts
│ ├── code-no-test-only.ts
│ ├── code-no-unexternalized-strings.ts
│ ├── code-no-unused-expressions.ts
│ ├── code-parameter-properties-must-have-explicit-accessibility.ts
│ ├── code-translation-remind.ts
│ ├── index.js
│ ├── package.json
│ ├── tsconfig.json
│ ├── utils.ts
│ ├── vscode-dts-cancellation.ts
│ ├── vscode-dts-create-func.ts
│ ├── vscode-dts-event-naming.ts
│ ├── vscode-dts-interface-naming.ts
│ ├── vscode-dts-literal-or-types.ts
│ ├── vscode-dts-provider-naming.ts
│ ├── vscode-dts-string-type-literals.ts
│ ├── vscode-dts-use-export.ts
│ ├── vscode-dts-use-thenable.ts
│ └── vscode-dts-vscode-in-comments.ts
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── config.yml
│ │ └── issue_template.md
│ ├── scripts/
│ │ └── issue_triage.py
│ └── workflows/
│ └── triage.yml
├── .gitignore
├── .idx/
│ └── dev.nix
├── .lsifrc.json
├── .mailmap
├── .mention-bot
├── .npmrc
├── .nvmrc
├── .voidrules
├── .vscode/
│ ├── cglicenses.schema.json
│ ├── extensions/
│ │ ├── vscode-selfhost-import-aid/
│ │ │ ├── .vscode/
│ │ │ │ ├── launch.json
│ │ │ │ └── settings.json
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ └── extension.ts
│ │ │ └── tsconfig.json
│ │ └── vscode-selfhost-test-provider/
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── settings.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── coverageProvider.ts
│ │ │ ├── debounce.ts
│ │ │ ├── extension.ts
│ │ │ ├── failingDeepStrictEqualAssertFixer.ts
│ │ │ ├── failureTracker.ts
│ │ │ ├── importGraph.ts
│ │ │ ├── memoize.ts
│ │ │ ├── metadata.ts
│ │ │ ├── snapshot.ts
│ │ │ ├── sourceUtils.ts
│ │ │ ├── stackTraceParser.ts
│ │ │ ├── streamSplitter.ts
│ │ │ ├── testOutputScanner.ts
│ │ │ ├── testTree.ts
│ │ │ ├── v8CoverageWrangling.test.ts
│ │ │ ├── v8CoverageWrangling.ts
│ │ │ └── vscodeTestRunner.ts
│ │ └── tsconfig.json
│ ├── extensions.json
│ ├── launch.json
│ ├── notebooks/
│ │ ├── api.github-issues
│ │ ├── endgame.github-issues
│ │ ├── grooming-delta.github-issues
│ │ ├── grooming.github-issues
│ │ ├── inbox.github-issues
│ │ ├── my-endgame.github-issues
│ │ ├── my-work.github-issues
│ │ ├── papercuts.github-issues
│ │ ├── verification.github-issues
│ │ └── vscode-dev.github-issues
│ ├── searches/
│ │ └── ts36031.code-search
│ ├── settings.json
│ ├── shared.code-snippets
│ └── tasks.json
├── .vscode-test.js
├── CodeQL.yml
├── HOW_TO_CONTRIBUTE.md
├── LICENSE-VS-Code.txt
├── LICENSE.txt
├── README.md
├── ThirdPartyNotices.txt
├── VOID_CODEBASE_GUIDE.md
├── build/
│ ├── .cachesalt
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .moduleignore
│ ├── .moduleignore.darwin
│ ├── .moduleignore.linux
│ ├── .moduleignore.win32
│ ├── .npmrc
│ ├── .webignore
│ ├── azure-pipelines/
│ │ ├── alpine/
│ │ │ ├── cli-build-alpine.yml
│ │ │ └── product-build-alpine.yml
│ │ ├── cli/
│ │ │ ├── cli-apply-patches.yml
│ │ │ ├── cli-compile.yml
│ │ │ ├── cli-darwin-sign.yml
│ │ │ ├── cli-win32-sign.yml
│ │ │ ├── install-rust-posix.yml
│ │ │ ├── install-rust-win32.yml
│ │ │ └── test.yml
│ │ ├── common/
│ │ │ ├── computeBuiltInDepsCacheKey.js
│ │ │ ├── computeBuiltInDepsCacheKey.ts
│ │ │ ├── computeNodeModulesCacheKey.js
│ │ │ ├── computeNodeModulesCacheKey.ts
│ │ │ ├── createBuild.js
│ │ │ ├── createBuild.ts
│ │ │ ├── extract-telemetry.sh
│ │ │ ├── getPublishAuthTokens.js
│ │ │ ├── getPublishAuthTokens.ts
│ │ │ ├── install-builtin-extensions.yml
│ │ │ ├── installPlaywright.js
│ │ │ ├── listNodeModules.js
│ │ │ ├── listNodeModules.ts
│ │ │ ├── publish.js
│ │ │ ├── publish.ts
│ │ │ ├── releaseBuild.js
│ │ │ ├── releaseBuild.ts
│ │ │ ├── retry.js
│ │ │ ├── retry.ts
│ │ │ ├── sign-win32.js
│ │ │ ├── sign-win32.ts
│ │ │ ├── sign.js
│ │ │ ├── sign.ts
│ │ │ └── telemetry-config.json
│ │ ├── config/
│ │ │ ├── CredScanSuppressions.json
│ │ │ └── tsaoptions.json
│ │ ├── darwin/
│ │ │ ├── app-entitlements.plist
│ │ │ ├── cli-build-darwin.yml
│ │ │ ├── helper-gpu-entitlements.plist
│ │ │ ├── helper-plugin-entitlements.plist
│ │ │ ├── helper-renderer-entitlements.plist
│ │ │ ├── product-build-darwin-cli-sign.yml
│ │ │ ├── product-build-darwin-sign.yml
│ │ │ ├── product-build-darwin-test.yml
│ │ │ ├── product-build-darwin-universal.yml
│ │ │ └── product-build-darwin.yml
│ │ ├── distro/
│ │ │ ├── download-distro.yml
│ │ │ ├── mixin-npm.js
│ │ │ ├── mixin-npm.ts
│ │ │ ├── mixin-quality.js
│ │ │ └── mixin-quality.ts
│ │ ├── distro-build.yml
│ │ ├── linux/
│ │ │ ├── .gitignore
│ │ │ ├── apt-retry.sh
│ │ │ ├── cli-build-linux.yml
│ │ │ ├── product-build-linux-test.yml
│ │ │ ├── product-build-linux.yml
│ │ │ ├── setup-env.sh
│ │ │ ├── snap-build-linux.yml
│ │ │ ├── verify-glibc-requirements.sh
│ │ │ └── xvfb.init
│ │ ├── oss/
│ │ │ ├── product-build-pr-cache-linux.yml
│ │ │ └── product-build-pr-cache-win32.yml
│ │ ├── product-build-pr.yml
│ │ ├── product-build.yml
│ │ ├── product-compile.yml
│ │ ├── product-npm-package-validate.yml
│ │ ├── product-publish.yml
│ │ ├── product-release.yml
│ │ ├── publish-types/
│ │ │ ├── check-version.js
│ │ │ ├── check-version.ts
│ │ │ ├── publish-types.yml
│ │ │ ├── update-types.js
│ │ │ └── update-types.ts
│ │ ├── upload-cdn.js
│ │ ├── upload-cdn.ts
│ │ ├── upload-nlsmetadata.js
│ │ ├── upload-nlsmetadata.ts
│ │ ├── upload-sourcemaps.js
│ │ ├── upload-sourcemaps.ts
│ │ ├── web/
│ │ │ └── product-build-web.yml
│ │ └── win32/
│ │ ├── cli-build-win32.yml
│ │ ├── exec.ps1
│ │ ├── import-esrp-auth-cert.ps1
│ │ ├── listprocesses.bat
│ │ ├── product-build-win32-cli-sign.yml
│ │ ├── product-build-win32-test.yml
│ │ ├── product-build-win32.yml
│ │ ├── retry.ps1
│ │ └── sdl-scan-win32.yml
│ ├── buildfile.js
│ ├── builtin/
│ │ ├── .eslintrc
│ │ ├── browser-main.js
│ │ ├── index.html
│ │ ├── main.js
│ │ └── package.json
│ ├── checksums/
│ │ ├── electron.txt
│ │ ├── nodejs.txt
│ │ └── vscode-sysroot.txt
│ ├── darwin/
│ │ ├── create-universal-app.js
│ │ ├── create-universal-app.ts
│ │ ├── sign.js
│ │ ├── sign.ts
│ │ ├── verify-macho.js
│ │ └── verify-macho.ts
│ ├── eslint.js
│ ├── filters.js
│ ├── gulp-eslint.js
│ ├── gulpfile.cli.js
│ ├── gulpfile.compile.js
│ ├── gulpfile.editor.js
│ ├── gulpfile.extensions.js
│ ├── gulpfile.hygiene.js
│ ├── gulpfile.js
│ ├── gulpfile.reh.js
│ ├── gulpfile.scan.js
│ ├── gulpfile.vscode.js
│ ├── gulpfile.vscode.linux.js
│ ├── gulpfile.vscode.web.js
│ ├── gulpfile.vscode.win32.js
│ ├── hygiene.js
│ ├── lib/
│ │ ├── asar.js
│ │ ├── asar.ts
│ │ ├── builtInExtensions.js
│ │ ├── builtInExtensions.ts
│ │ ├── builtInExtensionsCG.js
│ │ ├── builtInExtensionsCG.ts
│ │ ├── bundle.js
│ │ ├── bundle.ts
│ │ ├── compilation.js
│ │ ├── compilation.ts
│ │ ├── date.js
│ │ ├── date.ts
│ │ ├── dependencies.js
│ │ ├── dependencies.ts
│ │ ├── electron.js
│ │ ├── electron.ts
│ │ ├── extensions.js
│ │ ├── extensions.ts
│ │ ├── fetch.js
│ │ ├── fetch.ts
│ │ ├── formatter.js
│ │ ├── formatter.ts
│ │ ├── getVersion.js
│ │ ├── getVersion.ts
│ │ ├── git.js
│ │ ├── git.ts
│ │ ├── i18n.js
│ │ ├── i18n.resources.json
│ │ ├── i18n.ts
│ │ ├── inlineMeta.js
│ │ ├── inlineMeta.ts
│ │ ├── layersChecker.js
│ │ ├── layersChecker.ts
│ │ ├── mangle/
│ │ │ ├── index.js
│ │ │ ├── index.ts
│ │ │ ├── renameWorker.js
│ │ │ ├── renameWorker.ts
│ │ │ ├── staticLanguageServiceHost.js
│ │ │ └── staticLanguageServiceHost.ts
│ │ ├── monaco-api.js
│ │ ├── monaco-api.ts
│ │ ├── nls.js
│ │ ├── nls.ts
│ │ ├── node.js
│ │ ├── node.ts
│ │ ├── optimize.js
│ │ ├── optimize.ts
│ │ ├── policies.js
│ │ ├── policies.ts
│ │ ├── postcss.js
│ │ ├── postcss.ts
│ │ ├── preLaunch.js
│ │ ├── preLaunch.ts
│ │ ├── propertyInitOrderChecker.js
│ │ ├── propertyInitOrderChecker.ts
│ │ ├── reporter.js
│ │ ├── reporter.ts
│ │ ├── snapshotLoader.js
│ │ ├── snapshotLoader.ts
│ │ ├── standalone.js
│ │ ├── standalone.ts
│ │ ├── stats.js
│ │ ├── stats.ts
│ │ ├── stylelint/
│ │ │ ├── validateVariableNames.js
│ │ │ ├── validateVariableNames.ts
│ │ │ └── vscode-known-variables.json
│ │ ├── task.js
│ │ ├── task.ts
│ │ ├── test/
│ │ │ ├── i18n.test.js
│ │ │ └── i18n.test.ts
│ │ ├── treeshaking.js
│ │ ├── treeshaking.ts
│ │ ├── tsb/
│ │ │ ├── builder.js
│ │ │ ├── builder.ts
│ │ │ ├── index.js
│ │ │ ├── index.ts
│ │ │ ├── transpiler.js
│ │ │ ├── transpiler.ts
│ │ │ ├── utils.js
│ │ │ └── utils.ts
│ │ ├── typings/
│ │ │ ├── cgmanifest.json
│ │ │ ├── event-stream.d.ts
│ │ │ ├── github-releases.d.ts
│ │ │ ├── gulp-bom.d.ts
│ │ │ ├── gulp-buffer.d.ts
│ │ │ ├── gulp-flatmap.d.ts
│ │ │ ├── lazy.js.d.ts
│ │ │ ├── stream.d.ts
│ │ │ ├── ternary-stream.d.ts
│ │ │ └── vinyl.d.ts
│ │ ├── util.js
│ │ ├── util.ts
│ │ └── watch/
│ │ ├── index.js
│ │ ├── index.ts
│ │ ├── watch-win32.js
│ │ └── watch-win32.ts
│ ├── linux/
│ │ ├── debian/
│ │ │ ├── calculate-deps.js
│ │ │ ├── calculate-deps.ts
│ │ │ ├── dep-lists.js
│ │ │ ├── dep-lists.ts
│ │ │ ├── install-sysroot.js
│ │ │ ├── install-sysroot.ts
│ │ │ ├── types.js
│ │ │ └── types.ts
│ │ ├── dependencies-generator.js
│ │ ├── dependencies-generator.ts
│ │ ├── libcxx-fetcher.js
│ │ ├── libcxx-fetcher.ts
│ │ └── rpm/
│ │ ├── calculate-deps.js
│ │ ├── calculate-deps.ts
│ │ ├── dep-lists.js
│ │ ├── dep-lists.ts
│ │ ├── types.js
│ │ └── types.ts
│ ├── loader.min
│ ├── monaco/
│ │ ├── LICENSE
│ │ ├── README-npm.md
│ │ ├── README.md
│ │ ├── ThirdPartyNotices.txt
│ │ ├── monaco.d.ts.recipe
│ │ ├── monaco.usage.recipe
│ │ ├── package.json
│ │ └── version.txt
│ ├── npm/
│ │ ├── dirs.js
│ │ ├── gyp/
│ │ │ └── package.json
│ │ ├── jsconfig.json
│ │ ├── postinstall.js
│ │ ├── preinstall.js
│ │ ├── update-all-grammars.mjs
│ │ ├── update-distro.mjs
│ │ └── update-localization-extension.js
│ ├── package.json
│ ├── setup-npm-registry.js
│ ├── stylelint.js
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── win32/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── code.iss
│ ├── explorer-appx-fetcher.js
│ ├── explorer-appx-fetcher.ts
│ └── i18n/
│ ├── Default.hu.isl
│ ├── Default.ko.isl
│ ├── Default.zh-cn.isl
│ ├── Default.zh-tw.isl
│ ├── messages.de.isl
│ ├── messages.en.isl
│ ├── messages.es.isl
│ ├── messages.fr.isl
│ ├── messages.hu.isl
│ ├── messages.it.isl
│ ├── messages.ja.isl
│ ├── messages.ko.isl
│ ├── messages.pt-br.isl
│ ├── messages.ru.isl
│ ├── messages.tr.isl
│ ├── messages.zh-cn.isl
│ └── messages.zh-tw.isl
├── cglicenses.json
├── cgmanifest.json
├── cli/
│ ├── .cargo/
│ │ └── config.toml
│ ├── CONTRIBUTING.md
│ ├── Cargo.toml
│ ├── ThirdPartyNotices.txt
│ ├── build.rs
│ ├── rustfmt.toml
│ └── src/
│ ├── async_pipe.rs
│ ├── auth.rs
│ ├── bin/
│ │ └── code/
│ │ ├── legacy_args.rs
│ │ └── main.rs
│ ├── commands/
│ │ ├── args.rs
│ │ ├── context.rs
│ │ ├── output.rs
│ │ ├── serve_web.rs
│ │ ├── tunnels.rs
│ │ ├── update.rs
│ │ └── version.rs
│ ├── commands.rs
│ ├── constants.rs
│ ├── desktop/
│ │ └── version_manager.rs
│ ├── desktop.rs
│ ├── download_cache.rs
│ ├── json_rpc.rs
│ ├── lib.rs
│ ├── log.rs
│ ├── msgpack_rpc.rs
│ ├── options.rs
│ ├── rpc.rs
│ ├── self_update.rs
│ ├── singleton.rs
│ ├── state.rs
│ ├── tunnels/
│ │ ├── challenge.rs
│ │ ├── code_server.rs
│ │ ├── control_server.rs
│ │ ├── dev_tunnels.rs
│ │ ├── legal.rs
│ │ ├── local_forwarding.rs
│ │ ├── nosleep.rs
│ │ ├── nosleep_linux.rs
│ │ ├── nosleep_macos.rs
│ │ ├── nosleep_windows.rs
│ │ ├── paths.rs
│ │ ├── port_forwarder.rs
│ │ ├── protocol.rs
│ │ ├── server_bridge.rs
│ │ ├── server_multiplexer.rs
│ │ ├── service.rs
│ │ ├── service_linux.rs
│ │ ├── service_macos.rs
│ │ ├── service_windows.rs
│ │ ├── shutdown_signal.rs
│ │ ├── singleton_client.rs
│ │ ├── singleton_server.rs
│ │ ├── socket_signal.rs
│ │ └── wsl_detect.rs
│ ├── tunnels.rs
│ ├── update_service.rs
│ ├── util/
│ │ ├── app_lock.rs
│ │ ├── command.rs
│ │ ├── errors.rs
│ │ ├── file_lock.rs
│ │ ├── http.rs
│ │ ├── input.rs
│ │ ├── io.rs
│ │ ├── is_integrated.rs
│ │ ├── machine.rs
│ │ ├── os.rs
│ │ ├── prereqs.rs
│ │ ├── ring_buffer.rs
│ │ ├── sync.rs
│ │ ├── tar.rs
│ │ └── zipper.rs
│ └── util.rs
├── eslint.config.js
├── extensions/
│ ├── .npmrc
│ ├── bat/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── batchfile.code-snippets
│ │ └── syntaxes/
│ │ └── batchfile.tmLanguage.json
│ ├── cgmanifest.json
│ ├── clojure/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── clojure.tmLanguage.json
│ ├── coffeescript/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── coffeescript.code-snippets
│ │ └── syntaxes/
│ │ └── coffeescript.tmLanguage.json
│ ├── configuration-editing/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── schemas/
│ │ │ ├── attachContainer.schema.json
│ │ │ ├── devContainer.codespaces.schema.json
│ │ │ └── devContainer.vscode.schema.json
│ │ ├── src/
│ │ │ ├── browser/
│ │ │ │ └── net.ts
│ │ │ ├── configurationEditingMain.ts
│ │ │ ├── extensionsProposals.ts
│ │ │ ├── importExportProfiles.ts
│ │ │ ├── node/
│ │ │ │ └── net.ts
│ │ │ ├── settingsDocumentHelper.ts
│ │ │ ├── test/
│ │ │ │ ├── completion.test.ts
│ │ │ │ └── index.ts
│ │ │ └── typings/
│ │ │ └── ref.d.ts
│ │ └── tsconfig.json
│ ├── cpp/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammars.js
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ ├── c.code-snippets
│ │ │ └── cpp.code-snippets
│ │ └── syntaxes/
│ │ ├── c.tmLanguage.json
│ │ ├── cpp.embedded.macro.tmLanguage.json
│ │ ├── cpp.tmLanguage.json
│ │ ├── cuda-cpp.tmLanguage.json
│ │ └── platform.tmLanguage.json
│ ├── csharp/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── csharp.code-snippets
│ │ └── syntaxes/
│ │ └── csharp.tmLanguage.json
│ ├── css/
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── css.tmLanguage.json
│ ├── css-language-features/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ ├── settings.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── CONTRIBUTING.md
│ │ ├── README.md
│ │ ├── client/
│ │ │ ├── src/
│ │ │ │ ├── browser/
│ │ │ │ │ └── cssClientMain.ts
│ │ │ │ ├── cssClient.ts
│ │ │ │ ├── customData.ts
│ │ │ │ ├── dropOrPaste/
│ │ │ │ │ ├── dropOrPasteResource.ts
│ │ │ │ │ ├── shared.ts
│ │ │ │ │ └── uriList.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── cssClientMain.ts
│ │ │ │ │ └── nodeFs.ts
│ │ │ │ └── requests.ts
│ │ │ └── tsconfig.json
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── schemas/
│ │ │ └── package.schema.json
│ │ ├── server/
│ │ │ ├── .npmrc
│ │ │ ├── .vscode/
│ │ │ │ ├── launch.json
│ │ │ │ └── tasks.json
│ │ │ ├── extension-browser.webpack.config.js
│ │ │ ├── extension.webpack.config.js
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── cssServerMain.ts
│ │ │ │ │ └── cssServerWorkerMain.ts
│ │ │ │ ├── cssServer.ts
│ │ │ │ ├── customData.ts
│ │ │ │ ├── languageModelCache.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── cssServerMain.ts
│ │ │ │ │ ├── cssServerNodeMain.ts
│ │ │ │ │ └── nodeFs.ts
│ │ │ │ ├── requests.ts
│ │ │ │ ├── test/
│ │ │ │ │ ├── completion.test.ts
│ │ │ │ │ └── links.test.ts
│ │ │ │ └── utils/
│ │ │ │ ├── documentContext.ts
│ │ │ │ ├── runner.ts
│ │ │ │ ├── strings.ts
│ │ │ │ └── validation.ts
│ │ │ ├── test/
│ │ │ │ ├── index.js
│ │ │ │ ├── linksTestFixtures/
│ │ │ │ │ └── .gitignore
│ │ │ │ └── pathCompletionFixtures/
│ │ │ │ ├── .foo.js
│ │ │ │ ├── about/
│ │ │ │ │ ├── about.css
│ │ │ │ │ └── about.html
│ │ │ │ ├── index.html
│ │ │ │ ├── scss/
│ │ │ │ │ ├── _foo.scss
│ │ │ │ │ └── main.scss
│ │ │ │ └── src/
│ │ │ │ ├── data/
│ │ │ │ │ └── foo.asar
│ │ │ │ ├── feature.js
│ │ │ │ └── test.js
│ │ │ └── tsconfig.json
│ │ └── test/
│ │ └── mocha.opts
│ ├── dart/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── dart.tmLanguage.json
│ ├── debug-auto-launch/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── .vscodeignore
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ └── extension.ts
│ │ └── tsconfig.json
│ ├── debug-server-ready/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── .vscodeignore
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ └── extension.ts
│ │ └── tsconfig.json
│ ├── diff/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── diff.tmLanguage.json
│ ├── docker/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── docker.tmLanguage.json
│ ├── emmet/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── settings.json
│ │ ├── .vscodeignore
│ │ ├── CONTRIBUTING.md
│ │ ├── README.md
│ │ ├── cgmanifest.json
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── abbreviationActions.ts
│ │ │ ├── balance.ts
│ │ │ ├── browser/
│ │ │ │ └── emmetBrowserMain.ts
│ │ │ ├── bufferStream.ts
│ │ │ ├── defaultCompletionProvider.ts
│ │ │ ├── editPoint.ts
│ │ │ ├── emmetCommon.ts
│ │ │ ├── evaluateMathExpression.ts
│ │ │ ├── imageSizeHelper.ts
│ │ │ ├── incrementDecrement.ts
│ │ │ ├── locateFile.ts
│ │ │ ├── matchTag.ts
│ │ │ ├── mergeLines.ts
│ │ │ ├── node/
│ │ │ │ └── emmetNodeMain.ts
│ │ │ ├── parseDocument.ts
│ │ │ ├── reflectCssValue.ts
│ │ │ ├── removeTag.ts
│ │ │ ├── selectItem.ts
│ │ │ ├── selectItemHTML.ts
│ │ │ ├── selectItemStylesheet.ts
│ │ │ ├── splitJoinTag.ts
│ │ │ ├── test/
│ │ │ │ ├── abbreviationAction.test.ts
│ │ │ │ ├── completion.test.ts
│ │ │ │ ├── cssAbbreviationAction.test.ts
│ │ │ │ ├── editPointSelectItemBalance.test.ts
│ │ │ │ ├── evaluateMathExpression.test.ts
│ │ │ │ ├── incrementDecrement.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── partialParsingStylesheet.test.ts
│ │ │ │ ├── reflectCssValue.test.ts
│ │ │ │ ├── tagActions.test.ts
│ │ │ │ ├── testUtils.ts
│ │ │ │ ├── toggleComment.test.ts
│ │ │ │ ├── updateImageSize.test.ts
│ │ │ │ └── wrapWithAbbreviation.test.ts
│ │ │ ├── toggleComment.ts
│ │ │ ├── typings/
│ │ │ │ ├── EmmetFlatNode.d.ts
│ │ │ │ ├── EmmetNode.d.ts
│ │ │ │ ├── emmetio__css-parser.d.ts
│ │ │ │ ├── emmetio__html-matcher.d.ts
│ │ │ │ └── refs.d.ts
│ │ │ ├── updateImageSize.ts
│ │ │ ├── updateTag.ts
│ │ │ └── util.ts
│ │ ├── test-workspace/
│ │ │ └── .vscode/
│ │ │ └── settings.json
│ │ └── tsconfig.json
│ ├── esbuild-webview-common.js
│ ├── extension-editing/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── extensionEditingBrowserMain.ts
│ │ │ ├── extensionEditingMain.ts
│ │ │ ├── extensionEngineValidation.ts
│ │ │ ├── extensionLinter.ts
│ │ │ ├── jsonReconstruct.ts
│ │ │ └── packageDocumentHelper.ts
│ │ └── tsconfig.json
│ ├── fsharp/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── fsharp.code-snippets
│ │ └── syntaxes/
│ │ └── fsharp.tmLanguage.json
│ ├── git/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── build/
│ │ │ └── update-emoji.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── resources/
│ │ │ └── emojis.json
│ │ ├── src/
│ │ │ ├── actionButton.ts
│ │ │ ├── api/
│ │ │ │ ├── api1.ts
│ │ │ │ ├── extension.ts
│ │ │ │ └── git.d.ts
│ │ │ ├── askpass-empty.sh
│ │ │ ├── askpass-main.ts
│ │ │ ├── askpass.sh
│ │ │ ├── askpass.ts
│ │ │ ├── autofetch.ts
│ │ │ ├── blame.ts
│ │ │ ├── branchProtection.ts
│ │ │ ├── cache.ts
│ │ │ ├── commands.ts
│ │ │ ├── decorationProvider.ts
│ │ │ ├── decorators.ts
│ │ │ ├── diagnostics.ts
│ │ │ ├── editSessionIdentityProvider.ts
│ │ │ ├── emoji.ts
│ │ │ ├── fileSystemProvider.ts
│ │ │ ├── git-base.ts
│ │ │ ├── git-editor-empty.sh
│ │ │ ├── git-editor-main.ts
│ │ │ ├── git-editor.sh
│ │ │ ├── git.ts
│ │ │ ├── gitEditor.ts
│ │ │ ├── historyItemDetailsProvider.ts
│ │ │ ├── historyProvider.ts
│ │ │ ├── ipc/
│ │ │ │ ├── ipcClient.ts
│ │ │ │ └── ipcServer.ts
│ │ │ ├── main.ts
│ │ │ ├── model.ts
│ │ │ ├── operation.ts
│ │ │ ├── postCommitCommands.ts
│ │ │ ├── protocolHandler.ts
│ │ │ ├── pushError.ts
│ │ │ ├── remotePublisher.ts
│ │ │ ├── remoteSource.ts
│ │ │ ├── repository.ts
│ │ │ ├── ssh-askpass-empty.sh
│ │ │ ├── ssh-askpass.sh
│ │ │ ├── staging.ts
│ │ │ ├── statusbar.ts
│ │ │ ├── terminal.ts
│ │ │ ├── test/
│ │ │ │ ├── git.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── smoke.test.ts
│ │ │ ├── timelineProvider.ts
│ │ │ ├── typings/
│ │ │ │ └── git-base.d.ts
│ │ │ ├── uri.ts
│ │ │ ├── util.ts
│ │ │ └── watch.ts
│ │ └── tsconfig.json
│ ├── git-base/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── build/
│ │ │ └── update-grammars.js
│ │ ├── cgmanifest.json
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── languages/
│ │ │ ├── git-commit.language-configuration.json
│ │ │ ├── git-rebase.language-configuration.json
│ │ │ └── ignore.language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── api/
│ │ │ │ ├── api1.ts
│ │ │ │ ├── extension.ts
│ │ │ │ └── git-base.d.ts
│ │ │ ├── decorators.ts
│ │ │ ├── extension.ts
│ │ │ ├── model.ts
│ │ │ ├── remoteProvider.ts
│ │ │ ├── remoteSource.ts
│ │ │ └── util.ts
│ │ ├── syntaxes/
│ │ │ ├── git-commit.tmLanguage.json
│ │ │ ├── git-rebase.tmLanguage.json
│ │ │ └── ignore.tmLanguage.json
│ │ └── tsconfig.json
│ ├── github/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension.webpack.config.js
│ │ ├── markdown.css
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── auth.ts
│ │ │ ├── branchProtection.ts
│ │ │ ├── canonicalUriProvider.ts
│ │ │ ├── commands.ts
│ │ │ ├── credentialProvider.ts
│ │ │ ├── extension.ts
│ │ │ ├── historyItemDetailsProvider.ts
│ │ │ ├── links.ts
│ │ │ ├── publish.ts
│ │ │ ├── pushErrorHandler.ts
│ │ │ ├── remoteSourceProvider.ts
│ │ │ ├── remoteSourcePublisher.ts
│ │ │ ├── shareProviders.ts
│ │ │ ├── test/
│ │ │ │ ├── github.test.ts
│ │ │ │ └── index.ts
│ │ │ ├── typings/
│ │ │ │ ├── git-base.d.ts
│ │ │ │ ├── git.d.ts
│ │ │ │ └── ref.d.ts
│ │ │ └── util.ts
│ │ ├── testWorkspace/
│ │ │ ├── .github/
│ │ │ │ ├── PULL_REQUEST_TEMPLATE/
│ │ │ │ │ ├── a.md
│ │ │ │ │ ├── b.md
│ │ │ │ │ └── x.txt
│ │ │ │ └── PULL_REQUEST_TEMPLATE.md
│ │ │ ├── PULL_REQUEST_TEMPLATE/
│ │ │ │ ├── a.md
│ │ │ │ ├── b.md
│ │ │ │ └── x.txt
│ │ │ ├── PULL_REQUEST_TEMPLATE.md
│ │ │ ├── docs/
│ │ │ │ ├── PULL_REQUEST_TEMPLATE/
│ │ │ │ │ ├── a.md
│ │ │ │ │ ├── b.md
│ │ │ │ │ └── x.txt
│ │ │ │ └── PULL_REQUEST_TEMPLATE.md
│ │ │ ├── some-markdown.md
│ │ │ └── x.txt
│ │ └── tsconfig.json
│ ├── github-authentication/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── media/
│ │ │ ├── auth.css
│ │ │ └── index.html
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── browser/
│ │ │ │ ├── authServer.ts
│ │ │ │ ├── buffer.ts
│ │ │ │ ├── crypto.ts
│ │ │ │ └── fetch.ts
│ │ │ ├── common/
│ │ │ │ ├── env.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── experimentationService.ts
│ │ │ │ ├── keychain.ts
│ │ │ │ ├── logger.ts
│ │ │ │ └── utils.ts
│ │ │ ├── config.ts
│ │ │ ├── extension.ts
│ │ │ ├── flows.ts
│ │ │ ├── github.ts
│ │ │ ├── githubServer.ts
│ │ │ ├── node/
│ │ │ │ ├── authServer.ts
│ │ │ │ ├── buffer.ts
│ │ │ │ ├── crypto.ts
│ │ │ │ └── fetch.ts
│ │ │ └── test/
│ │ │ ├── flows.test.ts
│ │ │ └── node/
│ │ │ └── authServer.test.ts
│ │ └── tsconfig.json
│ ├── go/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── go.tmLanguage.json
│ ├── groovy/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── groovy.code-snippets
│ │ └── syntaxes/
│ │ └── groovy.tmLanguage.json
│ ├── grunt/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ └── main.ts
│ │ └── tsconfig.json
│ ├── gulp/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ └── main.ts
│ │ └── tsconfig.json
│ ├── handlebars/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── Handlebars.tmLanguage.json
│ ├── hlsl/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── hlsl.tmLanguage.json
│ ├── html/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammar.mjs
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── html.code-snippets
│ │ └── syntaxes/
│ │ ├── html-derivative.tmLanguage.json
│ │ └── html.tmLanguage.json
│ ├── html-language-features/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ ├── settings.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── CONTRIBUTING.md
│ │ ├── README.md
│ │ ├── build/
│ │ │ └── bundleTypeScriptLibraries.js
│ │ ├── cgmanifest.json
│ │ ├── client/
│ │ │ ├── src/
│ │ │ │ ├── autoInsertion.ts
│ │ │ │ ├── browser/
│ │ │ │ │ └── htmlClientMain.ts
│ │ │ │ ├── customData.ts
│ │ │ │ ├── htmlClient.ts
│ │ │ │ ├── languageParticipants.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── htmlClientMain.ts
│ │ │ │ │ └── nodeFs.ts
│ │ │ │ └── requests.ts
│ │ │ └── tsconfig.json
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── schemas/
│ │ │ └── package.schema.json
│ │ └── server/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── build/
│ │ │ └── javaScriptLibraryLoader.js
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── lib/
│ │ │ ├── cgmanifest.json
│ │ │ └── jquery.d.ts
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── browser/
│ │ │ │ ├── htmlServerMain.ts
│ │ │ │ └── htmlServerWorkerMain.ts
│ │ │ ├── customData.ts
│ │ │ ├── htmlServer.ts
│ │ │ ├── languageModelCache.ts
│ │ │ ├── modes/
│ │ │ │ ├── cssMode.ts
│ │ │ │ ├── embeddedSupport.ts
│ │ │ │ ├── formatting.ts
│ │ │ │ ├── htmlFolding.ts
│ │ │ │ ├── htmlMode.ts
│ │ │ │ ├── javascriptLibs.ts
│ │ │ │ ├── javascriptMode.ts
│ │ │ │ ├── javascriptSemanticTokens.ts
│ │ │ │ ├── languageModes.ts
│ │ │ │ ├── selectionRanges.ts
│ │ │ │ └── semanticTokens.ts
│ │ │ ├── node/
│ │ │ │ ├── htmlServerMain.ts
│ │ │ │ ├── htmlServerNodeMain.ts
│ │ │ │ └── nodeFs.ts
│ │ │ ├── requests.ts
│ │ │ ├── test/
│ │ │ │ ├── completions.test.ts
│ │ │ │ ├── documentContext.test.ts
│ │ │ │ ├── embedded.test.ts
│ │ │ │ ├── fixtures/
│ │ │ │ │ ├── expected/
│ │ │ │ │ │ ├── 19813-4spaces.html
│ │ │ │ │ │ ├── 19813-tab.html
│ │ │ │ │ │ ├── 19813.html
│ │ │ │ │ │ └── 21634.html
│ │ │ │ │ └── inputs/
│ │ │ │ │ ├── 19813.html
│ │ │ │ │ └── 21634.html
│ │ │ │ ├── folding.test.ts
│ │ │ │ ├── formatting.test.ts
│ │ │ │ ├── pathCompletionFixtures/
│ │ │ │ │ ├── .foo.js
│ │ │ │ │ ├── about/
│ │ │ │ │ │ ├── about.css
│ │ │ │ │ │ ├── about.html
│ │ │ │ │ │ └── media/
│ │ │ │ │ │ └── icon.pic
│ │ │ │ │ ├── index.html
│ │ │ │ │ └── src/
│ │ │ │ │ ├── feature.js
│ │ │ │ │ └── test.js
│ │ │ │ ├── rename.test.ts
│ │ │ │ ├── selectionRanges.test.ts
│ │ │ │ ├── semanticTokens.test.ts
│ │ │ │ └── words.test.ts
│ │ │ └── utils/
│ │ │ ├── arrays.ts
│ │ │ ├── documentContext.ts
│ │ │ ├── positions.ts
│ │ │ ├── runner.ts
│ │ │ ├── strings.ts
│ │ │ └── validation.ts
│ │ ├── test/
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── ini/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── ini.language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── properties.language-configuration.json
│ │ └── syntaxes/
│ │ └── ini.tmLanguage.json
│ ├── ipynb/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── esbuild.js
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── notebook-src/
│ │ │ └── cellAttachmentRenderer.ts
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── common.ts
│ │ │ ├── constants.ts
│ │ │ ├── deserializers.ts
│ │ │ ├── helper.ts
│ │ │ ├── ipynbMain.browser.ts
│ │ │ ├── ipynbMain.node.ts
│ │ │ ├── ipynbMain.ts
│ │ │ ├── notebookAttachmentCleaner.ts
│ │ │ ├── notebookImagePaste.ts
│ │ │ ├── notebookModelStoreSync.ts
│ │ │ ├── notebookSerializer.node.ts
│ │ │ ├── notebookSerializer.ts
│ │ │ ├── notebookSerializer.web.ts
│ │ │ ├── notebookSerializerWorker.ts
│ │ │ ├── notebookSerializerWorker.web.ts
│ │ │ ├── serializers.ts
│ │ │ ├── test/
│ │ │ │ ├── clearOutputs.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── notebookModelStoreSync.test.ts
│ │ │ │ └── serializers.test.ts
│ │ │ └── types.d.ts
│ │ └── tsconfig.json
│ ├── jake/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ └── main.ts
│ │ └── tsconfig.json
│ ├── java/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── java.code-snippets
│ │ └── syntaxes/
│ │ └── java.tmLanguage.json
│ ├── javascript/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── javascript-language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── javascript.code-snippets
│ │ ├── syntaxes/
│ │ │ ├── JavaScript.tmLanguage.json
│ │ │ ├── JavaScriptReact.tmLanguage.json
│ │ │ ├── Readme.md
│ │ │ └── Regular Expressions (JavaScript).tmLanguage
│ │ └── tags-language-configuration.json
│ ├── json/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammars.js
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ ├── JSON.tmLanguage.json
│ │ ├── JSONC.tmLanguage.json
│ │ ├── JSONL.tmLanguage.json
│ │ └── snippets.tmLanguage.json
│ ├── json-language-features/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── CONTRIBUTING.md
│ │ ├── README.md
│ │ ├── client/
│ │ │ ├── src/
│ │ │ │ ├── browser/
│ │ │ │ │ └── jsonClientMain.ts
│ │ │ │ ├── jsonClient.ts
│ │ │ │ ├── languageParticipants.ts
│ │ │ │ ├── languageStatus.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── jsonClientMain.ts
│ │ │ │ │ └── schemaCache.ts
│ │ │ │ └── utils/
│ │ │ │ └── hash.ts
│ │ │ └── tsconfig.json
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── server/
│ │ ├── .npmignore
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── README.md
│ │ ├── bin/
│ │ │ └── vscode-json-languageserver
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── browser/
│ │ │ │ ├── jsonServerMain.ts
│ │ │ │ └── jsonServerWorkerMain.ts
│ │ │ ├── jsonServer.ts
│ │ │ ├── languageModelCache.ts
│ │ │ ├── node/
│ │ │ │ ├── jsonServerMain.ts
│ │ │ │ └── jsonServerNodeMain.ts
│ │ │ └── utils/
│ │ │ ├── runner.ts
│ │ │ ├── strings.ts
│ │ │ └── validation.ts
│ │ ├── test/
│ │ │ └── mocha.opts
│ │ └── tsconfig.json
│ ├── julia/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── julia.tmLanguage.json
│ ├── latex/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammars.js
│ │ ├── cgmanifest.json
│ │ ├── cpp-bailout-license.txt
│ │ ├── latex-cpp-embedded-language-configuration.json
│ │ ├── latex-language-configuration.json
│ │ ├── markdown-latex-combined-language-configuration.json
│ │ ├── markdown-latex-combined-license.txt
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ ├── Bibtex.tmLanguage.json
│ │ ├── LaTeX.tmLanguage.json
│ │ ├── TeX.tmLanguage.json
│ │ ├── cpp-grammar-bailout.tmLanguage.json
│ │ └── markdown-latex-combined.tmLanguage.json
│ ├── less/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammar.js
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── less.tmLanguage.json
│ ├── log/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── log.tmLanguage.json
│ ├── lua/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── lua.tmLanguage.json
│ ├── make/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── make.tmLanguage.json
│ ├── mangle-loader.js
│ ├── markdown-basics/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── markdown.code-snippets
│ │ └── syntaxes/
│ │ └── markdown.tmLanguage.json
│ ├── markdown-language-features/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── esbuild-notebook.js
│ │ ├── esbuild-preview.js
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── media/
│ │ │ ├── highlight.css
│ │ │ └── markdown.css
│ │ ├── notebook/
│ │ │ ├── index.ts
│ │ │ └── tsconfig.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── preview-src/
│ │ │ ├── activeLineMarker.ts
│ │ │ ├── csp.ts
│ │ │ ├── events.ts
│ │ │ ├── index.ts
│ │ │ ├── loading.ts
│ │ │ ├── messaging.ts
│ │ │ ├── pre.ts
│ │ │ ├── scroll-sync.ts
│ │ │ ├── settings.ts
│ │ │ ├── strings.ts
│ │ │ └── tsconfig.json
│ │ ├── schemas/
│ │ │ └── package.schema.json
│ │ ├── src/
│ │ │ ├── client/
│ │ │ │ ├── client.ts
│ │ │ │ ├── fileWatchingManager.ts
│ │ │ │ ├── inMemoryDocument.ts
│ │ │ │ ├── protocol.ts
│ │ │ │ └── workspace.ts
│ │ │ ├── commandManager.ts
│ │ │ ├── commands/
│ │ │ │ ├── copyImage.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── insertResource.ts
│ │ │ │ ├── openImage.ts
│ │ │ │ ├── refreshPreview.ts
│ │ │ │ ├── reloadPlugins.ts
│ │ │ │ ├── renderDocument.ts
│ │ │ │ ├── showPreview.ts
│ │ │ │ ├── showPreviewSecuritySelector.ts
│ │ │ │ ├── showSource.ts
│ │ │ │ └── toggleLock.ts
│ │ │ ├── extension.browser.ts
│ │ │ ├── extension.shared.ts
│ │ │ ├── extension.ts
│ │ │ ├── languageFeatures/
│ │ │ │ ├── copyFiles/
│ │ │ │ │ ├── copyFiles.ts
│ │ │ │ │ ├── dropOrPasteResource.ts
│ │ │ │ │ ├── newFilePathGenerator.ts
│ │ │ │ │ ├── pasteUrlProvider.ts
│ │ │ │ │ ├── shared.ts
│ │ │ │ │ ├── smartDropOrPaste.ts
│ │ │ │ │ └── snippets.ts
│ │ │ │ ├── diagnostics.ts
│ │ │ │ ├── fileReferences.ts
│ │ │ │ ├── linkUpdater.ts
│ │ │ │ └── updateLinksOnPaste.ts
│ │ │ ├── logging.ts
│ │ │ ├── markdownEngine.ts
│ │ │ ├── markdownExtensions.ts
│ │ │ ├── preview/
│ │ │ │ ├── documentRenderer.ts
│ │ │ │ ├── preview.ts
│ │ │ │ ├── previewConfig.ts
│ │ │ │ ├── previewManager.ts
│ │ │ │ ├── scrolling.ts
│ │ │ │ ├── security.ts
│ │ │ │ └── topmostLineMonitor.ts
│ │ │ ├── slugify.ts
│ │ │ ├── telemetryReporter.ts
│ │ │ ├── test/
│ │ │ │ ├── copyFile.test.ts
│ │ │ │ ├── documentLink.test.ts
│ │ │ │ ├── engine.test.ts
│ │ │ │ ├── engine.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── nulLogging.ts
│ │ │ │ ├── pasteUrl.test.ts
│ │ │ │ ├── urlToUri.test.ts
│ │ │ │ └── util.ts
│ │ │ ├── types/
│ │ │ │ └── textDocument.ts
│ │ │ ├── typings/
│ │ │ │ └── ref.d.ts
│ │ │ └── util/
│ │ │ ├── arrays.ts
│ │ │ ├── async.ts
│ │ │ ├── cancellation.ts
│ │ │ ├── dispose.ts
│ │ │ ├── document.ts
│ │ │ ├── dom.ts
│ │ │ ├── file.ts
│ │ │ ├── mimes.ts
│ │ │ ├── openDocumentLink.ts
│ │ │ ├── resourceMap.ts
│ │ │ ├── resources.ts
│ │ │ ├── schemes.ts
│ │ │ ├── uriList.ts
│ │ │ └── url.ts
│ │ ├── test-workspace/
│ │ │ ├── a.md
│ │ │ ├── b.md
│ │ │ ├── sub/
│ │ │ │ ├── c.md
│ │ │ │ ├── d.md
│ │ │ │ ├── file with space.md
│ │ │ │ └── foo.txt
│ │ │ └── sub with space/
│ │ │ └── file.md
│ │ ├── tsconfig.browser.json
│ │ ├── tsconfig.json
│ │ └── types/
│ │ └── previewMessaging.d.ts
│ ├── markdown-math/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── cgmanifest.json
│ │ ├── esbuild.js
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── notebook/
│ │ │ ├── katex.ts
│ │ │ └── tsconfig.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── preview-styles/
│ │ │ └── index.css
│ │ ├── src/
│ │ │ └── extension.ts
│ │ ├── syntaxes/
│ │ │ ├── md-math-block.tmLanguage.json
│ │ │ ├── md-math-fence.tmLanguage.json
│ │ │ ├── md-math-inline.tmLanguage.json
│ │ │ └── md-math.tmLanguage.json
│ │ └── tsconfig.json
│ ├── media-preview/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── media/
│ │ │ ├── audioPreview.css
│ │ │ ├── audioPreview.js
│ │ │ ├── imagePreview.css
│ │ │ ├── imagePreview.js
│ │ │ ├── videoPreview.css
│ │ │ └── videoPreview.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── audioPreview.ts
│ │ │ ├── binarySizeStatusBarEntry.ts
│ │ │ ├── extension.ts
│ │ │ ├── imagePreview/
│ │ │ │ ├── index.ts
│ │ │ │ ├── sizeStatusBarEntry.ts
│ │ │ │ └── zoomStatusBarEntry.ts
│ │ │ ├── mediaPreview.ts
│ │ │ ├── ownedStatusBarEntry.ts
│ │ │ ├── util/
│ │ │ │ ├── dispose.ts
│ │ │ │ └── dom.ts
│ │ │ └── videoPreview.ts
│ │ └── tsconfig.json
│ ├── merge-conflict/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── codelensProvider.ts
│ │ │ ├── commandHandler.ts
│ │ │ ├── contentProvider.ts
│ │ │ ├── delayer.ts
│ │ │ ├── documentMergeConflict.ts
│ │ │ ├── documentTracker.ts
│ │ │ ├── interfaces.ts
│ │ │ ├── mergeConflictMain.ts
│ │ │ ├── mergeConflictParser.ts
│ │ │ ├── mergeDecorator.ts
│ │ │ └── services.ts
│ │ └── tsconfig.json
│ ├── microsoft-authentication/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── media/
│ │ │ ├── auth.css
│ │ │ └── index.html
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── packageMocks/
│ │ │ ├── dpapi/
│ │ │ │ └── dpapi.js
│ │ │ └── keytar/
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── src/
│ │ │ ├── AADHelper.ts
│ │ │ ├── UriEventHandler.ts
│ │ │ ├── betterSecretStorage.ts
│ │ │ ├── browser/
│ │ │ │ ├── authProvider.ts
│ │ │ │ ├── authServer.ts
│ │ │ │ ├── buffer.ts
│ │ │ │ └── fetch.ts
│ │ │ ├── common/
│ │ │ │ ├── accountAccess.ts
│ │ │ │ ├── async.ts
│ │ │ │ ├── cachePlugin.ts
│ │ │ │ ├── env.ts
│ │ │ │ ├── event.ts
│ │ │ │ ├── experimentation.ts
│ │ │ │ ├── loggerOptions.ts
│ │ │ │ ├── loopbackClientAndOpener.ts
│ │ │ │ ├── publicClientCache.ts
│ │ │ │ ├── scopeData.ts
│ │ │ │ ├── telemetryReporter.ts
│ │ │ │ ├── test/
│ │ │ │ │ ├── loopbackClientAndOpener.test.ts
│ │ │ │ │ └── scopeData.test.ts
│ │ │ │ └── uri.ts
│ │ │ ├── cryptoUtils.ts
│ │ │ ├── extension.ts
│ │ │ ├── extensionV1.ts
│ │ │ ├── extensionV2.ts
│ │ │ ├── logger.ts
│ │ │ └── node/
│ │ │ ├── authProvider.ts
│ │ │ ├── authServer.ts
│ │ │ ├── buffer.ts
│ │ │ ├── cachedPublicClientApplication.ts
│ │ │ ├── fetch.ts
│ │ │ ├── flows.ts
│ │ │ ├── loopbackTemplate.ts
│ │ │ └── publicClientCache.ts
│ │ └── tsconfig.json
│ ├── notebook-renderers/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── esbuild.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── ansi.ts
│ │ │ ├── color.ts
│ │ │ ├── colorMap.ts
│ │ │ ├── htmlHelper.ts
│ │ │ ├── index.ts
│ │ │ ├── linkify.ts
│ │ │ ├── rendererTypes.ts
│ │ │ ├── stackTraceHelper.ts
│ │ │ ├── test/
│ │ │ │ ├── index.ts
│ │ │ │ ├── linkify.test.ts
│ │ │ │ ├── notebookRenderer.test.ts
│ │ │ │ └── stackTraceHelper.test.ts
│ │ │ └── textHelper.ts
│ │ └── tsconfig.json
│ ├── npm/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── commands.ts
│ │ │ ├── features/
│ │ │ │ ├── bowerJSONContribution.ts
│ │ │ │ ├── date.ts
│ │ │ │ ├── jsonContributions.ts
│ │ │ │ └── packageJSONContribution.ts
│ │ │ ├── npmBrowserMain.ts
│ │ │ ├── npmMain.ts
│ │ │ ├── npmScriptLens.ts
│ │ │ ├── npmView.ts
│ │ │ ├── preferred-pm.ts
│ │ │ ├── readScripts.ts
│ │ │ ├── scriptHover.ts
│ │ │ └── tasks.ts
│ │ └── tsconfig.json
│ ├── objective-c/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammars.js
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ ├── objective-c++.tmLanguage.json
│ │ └── objective-c.tmLanguage.json
│ ├── open-remote-ssh/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── authResolver.ts
│ │ │ ├── commands.ts
│ │ │ ├── common/
│ │ │ │ ├── disposable.ts
│ │ │ │ ├── files.ts
│ │ │ │ ├── logger.ts
│ │ │ │ ├── platform.ts
│ │ │ │ └── ports.ts
│ │ │ ├── extension.ts
│ │ │ ├── hostTreeView.ts
│ │ │ ├── remoteLocationHistory.ts
│ │ │ ├── serverConfig.ts
│ │ │ ├── serverSetup.ts
│ │ │ └── ssh/
│ │ │ ├── hostfile.ts
│ │ │ ├── identityFiles.ts
│ │ │ ├── sshConfig.ts
│ │ │ ├── sshConnection.ts
│ │ │ └── sshDestination.ts
│ │ └── tsconfig.json
│ ├── open-remote-wsl/
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── authResolver.ts
│ │ │ ├── commands.ts
│ │ │ ├── common/
│ │ │ │ ├── async.ts
│ │ │ │ ├── disposable.ts
│ │ │ │ ├── event.ts
│ │ │ │ ├── files.ts
│ │ │ │ ├── logger.ts
│ │ │ │ ├── platform.ts
│ │ │ │ └── ports.ts
│ │ │ ├── distroTreeView.ts
│ │ │ ├── extension.ts
│ │ │ ├── remoteLocationHistory.ts
│ │ │ ├── serverConfig.ts
│ │ │ ├── serverSetup.ts
│ │ │ └── wsl/
│ │ │ ├── wslManager.ts
│ │ │ └── wslTerminal.ts
│ │ └── tsconfig.json
│ ├── package.json
│ ├── perl/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── perl.language-configuration.json
│ │ ├── perl6.language-configuration.json
│ │ └── syntaxes/
│ │ ├── perl.tmLanguage.json
│ │ └── perl6.tmLanguage.json
│ ├── php/
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammar.mjs
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── php.code-snippets
│ │ └── syntaxes/
│ │ ├── html.tmLanguage.json
│ │ └── php.tmLanguage.json
│ ├── php-language-features/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── features/
│ │ │ │ ├── completionItemProvider.ts
│ │ │ │ ├── hoverProvider.ts
│ │ │ │ ├── phpGlobalFunctions.ts
│ │ │ │ ├── phpGlobals.ts
│ │ │ │ ├── signatureHelpProvider.ts
│ │ │ │ ├── utils/
│ │ │ │ │ ├── async.ts
│ │ │ │ │ └── markedTextUtil.ts
│ │ │ │ └── validationProvider.ts
│ │ │ ├── phpMain.ts
│ │ │ └── typings/
│ │ │ └── node.additions.d.ts
│ │ └── tsconfig.json
│ ├── postinstall.mjs
│ ├── powershell/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── powershell.tmLanguage.json
│ ├── pug/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── pug.tmLanguage.json
│ ├── python/
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ ├── MagicPython.tmLanguage.json
│ │ └── MagicRegExp.tmLanguage.json
│ ├── r/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── r.tmLanguage.json
│ ├── razor/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammar.mjs
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── cshtml.tmLanguage.json
│ ├── references-view/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── calls/
│ │ │ │ ├── index.ts
│ │ │ │ └── model.ts
│ │ │ ├── extension.ts
│ │ │ ├── highlights.ts
│ │ │ ├── navigation.ts
│ │ │ ├── references/
│ │ │ │ ├── index.ts
│ │ │ │ └── model.ts
│ │ │ ├── references-view.d.ts
│ │ │ ├── tree.ts
│ │ │ ├── types/
│ │ │ │ ├── index.ts
│ │ │ │ └── model.ts
│ │ │ └── utils.ts
│ │ └── tsconfig.json
│ ├── restructuredtext/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── rst.tmLanguage.json
│ ├── ruby/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── ruby.tmLanguage.json
│ ├── rust/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammar.mjs
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── rust.tmLanguage.json
│ ├── scss/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ ├── sassdoc.tmLanguage.json
│ │ └── scss.tmLanguage.json
│ ├── search-result/
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ └── extension.ts
│ │ ├── syntaxes/
│ │ │ ├── generateTMLanguage.js
│ │ │ └── searchResult.tmLanguage.json
│ │ └── tsconfig.json
│ ├── shaderlab/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── shaderlab.tmLanguage.json
│ ├── shared.webpack.config.js
│ ├── shellscript/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── shell-unix-bash.tmLanguage.json
│ ├── simple-browser/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── esbuild-preview.js
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── media/
│ │ │ └── main.css
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── preview-src/
│ │ │ ├── events.ts
│ │ │ ├── index.ts
│ │ │ └── tsconfig.json
│ │ ├── src/
│ │ │ ├── dispose.ts
│ │ │ ├── extension.ts
│ │ │ ├── simpleBrowserManager.ts
│ │ │ └── simpleBrowserView.ts
│ │ └── tsconfig.json
│ ├── sql/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammar.mjs
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── syntaxes/
│ │ └── sql.tmLanguage.json
│ ├── swift/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── swift.code-snippets
│ │ └── syntaxes/
│ │ └── swift.tmLanguage.json
│ ├── terminal-suggest/
│ │ ├── .gitignore
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── ThirdPartyNotices.txt
│ │ ├── cgmanifest.json
│ │ ├── extension.webpack.config.js
│ │ ├── fixtures/
│ │ │ └── shell-parser/
│ │ │ ├── basic/
│ │ │ │ ├── input.sh
│ │ │ │ └── output.txt
│ │ │ ├── multipleStatements/
│ │ │ │ ├── input.sh
│ │ │ │ └── output.txt
│ │ │ ├── primaryExpressions/
│ │ │ │ ├── input.sh
│ │ │ │ └── output.txt
│ │ │ └── variables/
│ │ │ ├── input.sh
│ │ │ └── output.txt
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── scripts/
│ │ │ ├── clone-fig.ps1
│ │ │ ├── clone-fig.sh
│ │ │ ├── pullFishBuiltins.ts
│ │ │ ├── pullZshBuiltins.ts
│ │ │ ├── terminalScriptHelpers.ts
│ │ │ ├── update-specs.js
│ │ │ ├── update-specs.ps1
│ │ │ └── update-specs.sh
│ │ ├── src/
│ │ │ ├── completions/
│ │ │ │ ├── cd.ts
│ │ │ │ ├── code-insiders.ts
│ │ │ │ ├── code-tunnel-insiders.ts
│ │ │ │ ├── code-tunnel.ts
│ │ │ │ ├── code.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── npx.ts
│ │ │ │ ├── set-location.ts
│ │ │ │ └── upstream/
│ │ │ │ ├── apt.ts
│ │ │ │ ├── brew.ts
│ │ │ │ ├── cat.ts
│ │ │ │ ├── chmod.ts
│ │ │ │ ├── chown.ts
│ │ │ │ ├── cp.ts
│ │ │ │ ├── curl.ts
│ │ │ │ ├── df.ts
│ │ │ │ ├── du.ts
│ │ │ │ ├── echo.ts
│ │ │ │ ├── find.ts
│ │ │ │ ├── git.ts
│ │ │ │ ├── grep.ts
│ │ │ │ ├── head.ts
│ │ │ │ ├── kill.ts
│ │ │ │ ├── killall.ts
│ │ │ │ ├── less.ts
│ │ │ │ ├── ls.ts
│ │ │ │ ├── mkdir.ts
│ │ │ │ ├── more.ts
│ │ │ │ ├── mv.ts
│ │ │ │ ├── nano.ts
│ │ │ │ ├── node.ts
│ │ │ │ ├── npm.ts
│ │ │ │ ├── nvm.ts
│ │ │ │ ├── pnpm.ts
│ │ │ │ ├── ps.ts
│ │ │ │ ├── pwd.ts
│ │ │ │ ├── python.ts
│ │ │ │ ├── python3.ts
│ │ │ │ ├── rm.ts
│ │ │ │ ├── rmdir.ts
│ │ │ │ ├── scp.ts
│ │ │ │ ├── ssh.ts
│ │ │ │ ├── tail.ts
│ │ │ │ ├── top.ts
│ │ │ │ ├── touch.ts
│ │ │ │ ├── uname.ts
│ │ │ │ ├── vim.ts
│ │ │ │ ├── wget.ts
│ │ │ │ └── yarn.ts
│ │ │ ├── constants.ts
│ │ │ ├── env/
│ │ │ │ └── pathExecutableCache.ts
│ │ │ ├── fig/
│ │ │ │ ├── README.md
│ │ │ │ ├── api-bindings/
│ │ │ │ │ └── types.ts
│ │ │ │ ├── autocomplete/
│ │ │ │ │ ├── fig/
│ │ │ │ │ │ └── hooks.ts
│ │ │ │ │ ├── generators/
│ │ │ │ │ │ ├── cache.ts
│ │ │ │ │ │ ├── customSuggestionsGenerator.ts
│ │ │ │ │ │ ├── helpers.ts
│ │ │ │ │ │ └── scriptSuggestionsGenerator.ts
│ │ │ │ │ └── state/
│ │ │ │ │ ├── generators.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── autocomplete-parser/
│ │ │ │ │ ├── caches.ts
│ │ │ │ │ ├── errors.ts
│ │ │ │ │ └── parseArguments.ts
│ │ │ │ ├── execute.ts
│ │ │ │ ├── fig-autocomplete-shared/
│ │ │ │ │ ├── convert.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── mixins.ts
│ │ │ │ │ ├── revert.ts
│ │ │ │ │ ├── specMetadata.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── figInterface.ts
│ │ │ │ ├── shared/
│ │ │ │ │ ├── errors.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── internal.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── utils.test.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ └── shell-parser/
│ │ │ │ ├── command.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── parser.ts
│ │ │ │ └── test/
│ │ │ │ ├── command.test.ts
│ │ │ │ └── parser.test.ts
│ │ │ ├── helpers/
│ │ │ │ ├── completionItem.ts
│ │ │ │ ├── executable.ts
│ │ │ │ ├── file.ts
│ │ │ │ ├── filepaths.ts
│ │ │ │ ├── os.ts
│ │ │ │ ├── promise.ts
│ │ │ │ └── uri.ts
│ │ │ ├── shell/
│ │ │ │ ├── bash.ts
│ │ │ │ ├── common.ts
│ │ │ │ ├── fish.ts
│ │ │ │ ├── fishBuiltinsCache.ts
│ │ │ │ ├── pwsh.ts
│ │ │ │ ├── zsh.ts
│ │ │ │ └── zshBuiltinsCache.ts
│ │ │ ├── terminalSuggestMain.ts
│ │ │ ├── test/
│ │ │ │ ├── completions/
│ │ │ │ │ ├── cd.test.ts
│ │ │ │ │ ├── code-insiders.test.ts
│ │ │ │ │ ├── code.test.ts
│ │ │ │ │ └── upstream/
│ │ │ │ │ ├── echo.test.ts
│ │ │ │ │ ├── git.test.ts
│ │ │ │ │ ├── ls.test.ts
│ │ │ │ │ ├── mkdir.test.ts
│ │ │ │ │ ├── rm.test.ts
│ │ │ │ │ ├── rmdir.test.ts
│ │ │ │ │ └── touch.test.ts
│ │ │ │ ├── env/
│ │ │ │ │ └── pathExecutableCache.test.ts
│ │ │ │ ├── fig.test.ts
│ │ │ │ ├── helpers.ts
│ │ │ │ ├── terminalSuggestMain.test.ts
│ │ │ │ └── tokens.test.ts
│ │ │ ├── tokens.ts
│ │ │ └── types.ts
│ │ ├── testWorkspace/
│ │ │ └── parent/
│ │ │ └── home/
│ │ │ └── child/
│ │ │ └── .keep
│ │ └── tsconfig.json
│ ├── theme-abyss/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── abyss-color-theme.json
│ ├── theme-defaults/
│ │ ├── fileicons/
│ │ │ └── vs_minimal-icon-theme.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ ├── dark_modern.json
│ │ ├── dark_plus.json
│ │ ├── dark_vs.json
│ │ ├── hc_black.json
│ │ ├── hc_light.json
│ │ ├── light_modern.json
│ │ ├── light_plus.json
│ │ └── light_vs.json
│ ├── theme-kimbie-dark/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── kimbie-dark-color-theme.json
│ ├── theme-monokai/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── monokai-color-theme.json
│ ├── theme-monokai-dimmed/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── dimmed-monokai-color-theme.json
│ ├── theme-quietlight/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── quietlight-color-theme.json
│ ├── theme-red/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── Red-color-theme.json
│ ├── theme-seti/
│ │ ├── .vscodeignore
│ │ ├── CONTRIBUTING.md
│ │ ├── README.md
│ │ ├── ThirdPartyNotices.txt
│ │ ├── build/
│ │ │ └── update-icon-theme.js
│ │ ├── cgmanifest.json
│ │ ├── icons/
│ │ │ ├── preview.html
│ │ │ └── vs-seti-icon-theme.json
│ │ ├── package.json
│ │ └── package.nls.json
│ ├── theme-solarized-dark/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── solarized-dark-color-theme.json
│ ├── theme-solarized-light/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── solarized-light-color-theme.json
│ ├── theme-tomorrow-night-blue/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ └── themes/
│ │ └── tomorrow-night-blue-color-theme.json
│ ├── tsconfig.base.json
│ ├── tunnel-forwarding/
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── .vscodeignore
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── src/
│ │ │ ├── deferredPromise.ts
│ │ │ ├── extension.ts
│ │ │ └── split.ts
│ │ └── tsconfig.json
│ ├── types/
│ │ ├── lib.textEncoder.d.ts
│ │ └── lib.url.d.ts
│ ├── typescript-basics/
│ │ ├── .vscodeignore
│ │ ├── build/
│ │ │ └── update-grammars.mjs
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── typescript.code-snippets
│ │ └── syntaxes/
│ │ ├── Readme.md
│ │ ├── TypeScript.tmLanguage.json
│ │ ├── TypeScriptReact.tmLanguage.json
│ │ ├── jsdoc.js.injection.tmLanguage.json
│ │ └── jsdoc.ts.injection.tmLanguage.json
│ ├── typescript-language-features/
│ │ ├── .npmrc
│ │ ├── .vscodeignore
│ │ ├── README.md
│ │ ├── cgmanifest.json
│ │ ├── extension-browser.webpack.config.js
│ │ ├── extension.webpack.config.js
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── schemas/
│ │ │ ├── jsconfig.schema.json
│ │ │ ├── package.schema.json
│ │ │ └── tsconfig.schema.json
│ │ ├── src/
│ │ │ ├── api.ts
│ │ │ ├── commands/
│ │ │ │ ├── commandManager.ts
│ │ │ │ ├── configurePlugin.ts
│ │ │ │ ├── goToProjectConfiguration.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── learnMoreAboutRefactorings.ts
│ │ │ │ ├── openJsDocLink.ts
│ │ │ │ ├── openTsServerLog.ts
│ │ │ │ ├── reloadProject.ts
│ │ │ │ ├── restartTsServer.ts
│ │ │ │ ├── selectTypeScriptVersion.ts
│ │ │ │ └── tsserverRequests.ts
│ │ │ ├── configuration/
│ │ │ │ ├── configuration.browser.ts
│ │ │ │ ├── configuration.electron.ts
│ │ │ │ ├── configuration.ts
│ │ │ │ ├── documentSelector.ts
│ │ │ │ ├── fileSchemes.ts
│ │ │ │ ├── languageDescription.ts
│ │ │ │ ├── languageIds.ts
│ │ │ │ └── schemes.ts
│ │ │ ├── experimentTelemetryReporter.ts
│ │ │ ├── experimentationService.ts
│ │ │ ├── extension.browser.ts
│ │ │ ├── extension.ts
│ │ │ ├── filesystems/
│ │ │ │ ├── ata.ts
│ │ │ │ ├── autoInstallerFs.ts
│ │ │ │ └── memFs.ts
│ │ │ ├── languageFeatures/
│ │ │ │ ├── callHierarchy.ts
│ │ │ │ ├── codeLens/
│ │ │ │ │ ├── baseCodeLensProvider.ts
│ │ │ │ │ ├── implementationsCodeLens.ts
│ │ │ │ │ └── referencesCodeLens.ts
│ │ │ │ ├── completions.ts
│ │ │ │ ├── copyPaste.ts
│ │ │ │ ├── definitionProviderBase.ts
│ │ │ │ ├── definitions.ts
│ │ │ │ ├── diagnostics.ts
│ │ │ │ ├── directiveCommentCompletions.ts
│ │ │ │ ├── documentHighlight.ts
│ │ │ │ ├── documentSymbol.ts
│ │ │ │ ├── fileConfigurationManager.ts
│ │ │ │ ├── fileReferences.ts
│ │ │ │ ├── fixAll.ts
│ │ │ │ ├── folding.ts
│ │ │ │ ├── formatting.ts
│ │ │ │ ├── hover.ts
│ │ │ │ ├── implementations.ts
│ │ │ │ ├── inlayHints.ts
│ │ │ │ ├── jsDocCompletions.ts
│ │ │ │ ├── linkedEditing.ts
│ │ │ │ ├── organizeImports.ts
│ │ │ │ ├── quickFix.ts
│ │ │ │ ├── refactor.ts
│ │ │ │ ├── references.ts
│ │ │ │ ├── rename.ts
│ │ │ │ ├── semanticTokens.ts
│ │ │ │ ├── signatureHelp.ts
│ │ │ │ ├── smartSelect.ts
│ │ │ │ ├── sourceDefinition.ts
│ │ │ │ ├── tagClosing.ts
│ │ │ │ ├── tsconfig.ts
│ │ │ │ ├── typeDefinitions.ts
│ │ │ │ ├── updatePathsOnRename.ts
│ │ │ │ ├── util/
│ │ │ │ │ ├── codeAction.ts
│ │ │ │ │ ├── copilot.ts
│ │ │ │ │ ├── dependentRegistration.ts
│ │ │ │ │ ├── snippetForFunctionCall.ts
│ │ │ │ │ └── textRendering.ts
│ │ │ │ └── workspaceSymbols.ts
│ │ │ ├── languageProvider.ts
│ │ │ ├── lazyClientHost.ts
│ │ │ ├── logging/
│ │ │ │ ├── logLevelMonitor.ts
│ │ │ │ ├── logger.ts
│ │ │ │ ├── telemetry.ts
│ │ │ │ └── tracer.ts
│ │ │ ├── remoteRepositories.browser.ts
│ │ │ ├── task/
│ │ │ │ ├── taskProvider.ts
│ │ │ │ └── tsconfigProvider.ts
│ │ │ ├── test/
│ │ │ │ ├── index.ts
│ │ │ │ ├── smoke/
│ │ │ │ │ ├── completions.test.ts
│ │ │ │ │ ├── fixAll.test.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── jsDocCompletions.test.ts
│ │ │ │ │ ├── quickFix.test.ts
│ │ │ │ │ └── referencesCodeLens.test.ts
│ │ │ │ ├── suggestTestHelpers.ts
│ │ │ │ ├── testUtils.ts
│ │ │ │ └── unit/
│ │ │ │ ├── cachedResponse.test.ts
│ │ │ │ ├── functionCallSnippet.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jsdocSnippet.test.ts
│ │ │ │ ├── onEnter.test.ts
│ │ │ │ ├── requestQueue.test.ts
│ │ │ │ ├── server.test.ts
│ │ │ │ └── textRendering.test.ts
│ │ │ ├── test-all.ts
│ │ │ ├── tsServer/
│ │ │ │ ├── api.ts
│ │ │ │ ├── bufferSyncSupport.ts
│ │ │ │ ├── cachedResponse.ts
│ │ │ │ ├── callbackMap.ts
│ │ │ │ ├── cancellation.electron.ts
│ │ │ │ ├── cancellation.ts
│ │ │ │ ├── fileWatchingManager.ts
│ │ │ │ ├── logDirectoryProvider.electron.ts
│ │ │ │ ├── logDirectoryProvider.ts
│ │ │ │ ├── nodeManager.ts
│ │ │ │ ├── pluginPathsProvider.ts
│ │ │ │ ├── plugins.ts
│ │ │ │ ├── protocol/
│ │ │ │ │ ├── errorCodes.ts
│ │ │ │ │ ├── fixNames.ts
│ │ │ │ │ ├── modifiers.ts
│ │ │ │ │ ├── protocol.const.ts
│ │ │ │ │ └── protocol.d.ts
│ │ │ │ ├── requestQueue.ts
│ │ │ │ ├── server.ts
│ │ │ │ ├── serverError.ts
│ │ │ │ ├── serverProcess.browser.ts
│ │ │ │ ├── serverProcess.electron.ts
│ │ │ │ ├── spawner.ts
│ │ │ │ ├── versionManager.ts
│ │ │ │ ├── versionProvider.electron.ts
│ │ │ │ └── versionProvider.ts
│ │ │ ├── tsconfig.ts
│ │ │ ├── typeConverters.ts
│ │ │ ├── typeScriptServiceClientHost.ts
│ │ │ ├── typescriptService.ts
│ │ │ ├── typescriptServiceClient.ts
│ │ │ ├── ui/
│ │ │ │ ├── activeJsTsEditorTracker.ts
│ │ │ │ ├── intellisenseStatus.ts
│ │ │ │ ├── largeProjectStatus.ts
│ │ │ │ ├── managedFileContext.ts
│ │ │ │ ├── typingsStatus.ts
│ │ │ │ └── versionStatus.ts
│ │ │ └── utils/
│ │ │ ├── arrays.ts
│ │ │ ├── async.ts
│ │ │ ├── cancellation.ts
│ │ │ ├── dispose.ts
│ │ │ ├── fs.electron.ts
│ │ │ ├── fs.ts
│ │ │ ├── hash.ts
│ │ │ ├── lazy.ts
│ │ │ ├── memoize.ts
│ │ │ ├── objects.ts
│ │ │ ├── packageInfo.ts
│ │ │ ├── platform.ts
│ │ │ ├── regexp.ts
│ │ │ ├── relativePathResolver.ts
│ │ │ ├── resourceMap.ts
│ │ │ └── temp.electron.ts
│ │ ├── test-workspace/
│ │ │ ├── bar.ts
│ │ │ ├── foo.ts
│ │ │ ├── foojs.js
│ │ │ ├── index.ts
│ │ │ └── tsconfig.json
│ │ ├── tsconfig.json
│ │ └── web/
│ │ ├── README.md
│ │ ├── src/
│ │ │ ├── fileWatcherManager.ts
│ │ │ ├── logging.ts
│ │ │ ├── pathMapper.ts
│ │ │ ├── serverHost.ts
│ │ │ ├── typingsInstaller/
│ │ │ │ ├── jsTyping.ts
│ │ │ │ └── typingsInstaller.ts
│ │ │ ├── util/
│ │ │ │ ├── args.ts
│ │ │ │ └── hrtime.ts
│ │ │ ├── wasmCancellationToken.ts
│ │ │ ├── webServer.ts
│ │ │ └── workerSession.ts
│ │ └── tsconfig.json
│ ├── vb/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── language-configuration.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── snippets/
│ │ │ └── vb.code-snippets
│ │ └── syntaxes/
│ │ └── asp-vb-net.tmLanguage.json
│ ├── vscode-api-tests/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── .vscodeignore
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── extension.ts
│ │ │ ├── memfs.ts
│ │ │ ├── singlefolder-tests/
│ │ │ │ ├── chat.test.ts
│ │ │ │ ├── commands.test.ts
│ │ │ │ ├── configuration.test.ts
│ │ │ │ ├── debug.test.ts
│ │ │ │ ├── documentPaste.test.ts
│ │ │ │ ├── editor.test.ts
│ │ │ │ ├── env.test.ts
│ │ │ │ ├── extensions.test.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── interactiveWindow.test.ts
│ │ │ │ ├── ipynb.test.ts
│ │ │ │ ├── languagedetection.test.ts
│ │ │ │ ├── languages.test.ts
│ │ │ │ ├── lm.test.ts
│ │ │ │ ├── notebook.api.test.ts
│ │ │ │ ├── notebook.document.test.ts
│ │ │ │ ├── notebook.editor.test.ts
│ │ │ │ ├── notebook.kernel.test.ts
│ │ │ │ ├── proxy.test.ts
│ │ │ │ ├── quickInput.test.ts
│ │ │ │ ├── readonlyFileSystem.test.ts
│ │ │ │ ├── rpc.test.ts
│ │ │ │ ├── state.test.ts
│ │ │ │ ├── terminal.shellIntegration.test.ts
│ │ │ │ ├── terminal.test.ts
│ │ │ │ ├── types.test.ts
│ │ │ │ ├── window.test.ts
│ │ │ │ ├── workspace.event.test.ts
│ │ │ │ ├── workspace.fs.test.ts
│ │ │ │ ├── workspace.tasks.test.ts
│ │ │ │ ├── workspace.test.ts
│ │ │ │ └── workspace.watcher.test.ts
│ │ │ ├── utils.ts
│ │ │ └── workspace-tests/
│ │ │ ├── index.ts
│ │ │ └── workspace.test.ts
│ │ ├── testWorkspace/
│ │ │ ├── .vscode/
│ │ │ │ ├── launch.json
│ │ │ │ └── settings.json
│ │ │ ├── 10linefile.ts
│ │ │ ├── 30linefile.ts
│ │ │ ├── bower.json
│ │ │ ├── debug.js
│ │ │ ├── far.js
│ │ │ ├── files-exclude/
│ │ │ │ └── file.txt
│ │ │ ├── lorem.txt
│ │ │ ├── myFile.ts
│ │ │ ├── search-exclude/
│ │ │ │ └── file.txt
│ │ │ ├── simple.txt
│ │ │ └── test.ipynb
│ │ ├── testWorkspace2/
│ │ │ ├── .vscode/
│ │ │ │ └── settings.json
│ │ │ └── simple.txt
│ │ ├── testworkspace.code-workspace
│ │ └── tsconfig.json
│ ├── vscode-colorize-perf-tests/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── colorizer.test.ts
│ │ │ ├── colorizerTestMain.ts
│ │ │ └── index.ts
│ │ ├── test/
│ │ │ └── colorize-fixtures/
│ │ │ ├── test-checker.ts
│ │ │ ├── test-treeView.ts
│ │ │ └── test.ts
│ │ └── tsconfig.json
│ ├── vscode-colorize-tests/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── package.json
│ │ ├── producticons/
│ │ │ ├── index.html
│ │ │ ├── mit_license.txt
│ │ │ └── test-product-icon-theme.json
│ │ ├── src/
│ │ │ ├── colorizer.test.ts
│ │ │ ├── colorizerTestMain.ts
│ │ │ └── index.ts
│ │ ├── test/
│ │ │ ├── colorize-fixtures/
│ │ │ │ ├── 12750.html
│ │ │ │ ├── 13448.html
│ │ │ │ ├── 14119.less
│ │ │ │ ├── 25920.html
│ │ │ │ ├── COMMIT_EDITMSG
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── basic.java
│ │ │ │ ├── git-rebase-todo
│ │ │ │ ├── issue-1550.yaml
│ │ │ │ ├── issue-224862.yaml
│ │ │ │ ├── issue-28354.php
│ │ │ │ ├── issue-4008.yaml
│ │ │ │ ├── issue-6303.yaml
│ │ │ │ ├── issue-76997.php
│ │ │ │ ├── makefile
│ │ │ │ ├── md-math.md
│ │ │ │ ├── test-13777.go
│ │ │ │ ├── test-166781.rs
│ │ │ │ ├── test-173216.sh
│ │ │ │ ├── test-173224.sh
│ │ │ │ ├── test-173336.sh
│ │ │ │ ├── test-23630.cpp
│ │ │ │ ├── test-23850.cpp
│ │ │ │ ├── test-241001.ts
│ │ │ │ ├── test-33886.md
│ │ │ │ ├── test-4287.pug
│ │ │ │ ├── test-6611.rs
│ │ │ │ ├── test-7115.xml
│ │ │ │ ├── test-78769.cpp
│ │ │ │ ├── test-80644.cpp
│ │ │ │ ├── test-brackets.tsx
│ │ │ │ ├── test-cssvariables.less
│ │ │ │ ├── test-cssvariables.scss
│ │ │ │ ├── test-embedding.html
│ │ │ │ ├── test-freeze-56377.py
│ │ │ │ ├── test-freeze-56476.ps1
│ │ │ │ ├── test-function-inv.ts
│ │ │ │ ├── test-issue11.ts
│ │ │ │ ├── test-issue241715.ts
│ │ │ │ ├── test-issue5431.ts
│ │ │ │ ├── test-issue5465.ts
│ │ │ │ ├── test-issue5566.ts
│ │ │ │ ├── test-jsdoc-multiline-type.ts
│ │ │ │ ├── test-keywords.ts
│ │ │ │ ├── test-members.ts
│ │ │ │ ├── test-object-literals.ts
│ │ │ │ ├── test-regex.coffee
│ │ │ │ ├── test-strings.ts
│ │ │ │ ├── test-this.ts
│ │ │ │ ├── test-variables.css
│ │ │ │ ├── test.bat
│ │ │ │ ├── test.bib
│ │ │ │ ├── test.c
│ │ │ │ ├── test.cc
│ │ │ │ ├── test.clj
│ │ │ │ ├── test.code-snippets
│ │ │ │ ├── test.coffee
│ │ │ │ ├── test.cpp
│ │ │ │ ├── test.cs
│ │ │ │ ├── test.cshtml
│ │ │ │ ├── test.css
│ │ │ │ ├── test.cu
│ │ │ │ ├── test.dart
│ │ │ │ ├── test.diff
│ │ │ │ ├── test.fs
│ │ │ │ ├── test.go
│ │ │ │ ├── test.groovy
│ │ │ │ ├── test.handlebars
│ │ │ │ ├── test.hbs
│ │ │ │ ├── test.hlsl
│ │ │ │ ├── test.html
│ │ │ │ ├── test.ini
│ │ │ │ ├── test.jl
│ │ │ │ ├── test.js
│ │ │ │ ├── test.json
│ │ │ │ ├── test.jsx
│ │ │ │ ├── test.less
│ │ │ │ ├── test.log
│ │ │ │ ├── test.lua
│ │ │ │ ├── test.m
│ │ │ │ ├── test.md
│ │ │ │ ├── test.mm
│ │ │ │ ├── test.p6
│ │ │ │ ├── test.php
│ │ │ │ ├── test.pl
│ │ │ │ ├── test.ps1
│ │ │ │ ├── test.pug
│ │ │ │ ├── test.py
│ │ │ │ ├── test.r
│ │ │ │ ├── test.rb
│ │ │ │ ├── test.regexp.ts
│ │ │ │ ├── test.rs
│ │ │ │ ├── test.rst
│ │ │ │ ├── test.scss
│ │ │ │ ├── test.sh
│ │ │ │ ├── test.shader
│ │ │ │ ├── test.sql
│ │ │ │ ├── test.sty
│ │ │ │ ├── test.swift
│ │ │ │ ├── test.tex
│ │ │ │ ├── test.ts
│ │ │ │ ├── test.vb
│ │ │ │ ├── test.xml
│ │ │ │ ├── test.yaml
│ │ │ │ ├── test2.pl
│ │ │ │ ├── test6916.js
│ │ │ │ └── tsconfig_off.json
│ │ │ ├── colorize-results/
│ │ │ │ ├── 12750_html.json
│ │ │ │ ├── 13448_html.json
│ │ │ │ ├── 14119_less.json
│ │ │ │ ├── 25920_html.json
│ │ │ │ ├── COMMIT_EDITMSG.json
│ │ │ │ ├── Dockerfile.json
│ │ │ │ ├── basic_java.json
│ │ │ │ ├── git-rebase-todo.json
│ │ │ │ ├── issue-1550_yaml.json
│ │ │ │ ├── issue-224862_yaml.json
│ │ │ │ ├── issue-28354_php.json
│ │ │ │ ├── issue-4008_yaml.json
│ │ │ │ ├── issue-6303_yaml.json
│ │ │ │ ├── issue-76997_php.json
│ │ │ │ ├── makefile.json
│ │ │ │ ├── md-math_md.json
│ │ │ │ ├── test-13777_go.json
│ │ │ │ ├── test-166781_rs.json
│ │ │ │ ├── test-173216_sh.json
│ │ │ │ ├── test-173224_sh.json
│ │ │ │ ├── test-173336_sh.json
│ │ │ │ ├── test-23630_cpp.json
│ │ │ │ ├── test-23850_cpp.json
│ │ │ │ ├── test-241001_ts.json
│ │ │ │ ├── test-33886_md.json
│ │ │ │ ├── test-4287_pug.json
│ │ │ │ ├── test-6611_rs.json
│ │ │ │ ├── test-7115_xml.json
│ │ │ │ ├── test-78769_cpp.json
│ │ │ │ ├── test-80644_cpp.json
│ │ │ │ ├── test-brackets_tsx.json
│ │ │ │ ├── test-cssvariables_less.json
│ │ │ │ ├── test-cssvariables_scss.json
│ │ │ │ ├── test-embedding_html.json
│ │ │ │ ├── test-freeze-56377_py.json
│ │ │ │ ├── test-freeze-56476_ps1.json
│ │ │ │ ├── test-function-inv_ts.json
│ │ │ │ ├── test-issue11_ts.json
│ │ │ │ ├── test-issue241715_ts.json
│ │ │ │ ├── test-issue5431_ts.json
│ │ │ │ ├── test-issue5465_ts.json
│ │ │ │ ├── test-issue5566_ts.json
│ │ │ │ ├── test-jsdoc-multiline-type_ts.json
│ │ │ │ ├── test-keywords_ts.json
│ │ │ │ ├── test-members_ts.json
│ │ │ │ ├── test-object-literals_ts.json
│ │ │ │ ├── test-regex_coffee.json
│ │ │ │ ├── test-strings_ts.json
│ │ │ │ ├── test-this_ts.json
│ │ │ │ ├── test-variables_css.json
│ │ │ │ ├── test2_pl.json
│ │ │ │ ├── test6916_js.json
│ │ │ │ ├── test_bat.json
│ │ │ │ ├── test_bib.json
│ │ │ │ ├── test_c.json
│ │ │ │ ├── test_cc.json
│ │ │ │ ├── test_clj.json
│ │ │ │ ├── test_code-snippets.json
│ │ │ │ ├── test_coffee.json
│ │ │ │ ├── test_cpp.json
│ │ │ │ ├── test_cs.json
│ │ │ │ ├── test_cshtml.json
│ │ │ │ ├── test_css.json
│ │ │ │ ├── test_cu.json
│ │ │ │ ├── test_dart.json
│ │ │ │ ├── test_diff.json
│ │ │ │ ├── test_fs.json
│ │ │ │ ├── test_go.json
│ │ │ │ ├── test_groovy.json
│ │ │ │ ├── test_handlebars.json
│ │ │ │ ├── test_hbs.json
│ │ │ │ ├── test_hlsl.json
│ │ │ │ ├── test_html.json
│ │ │ │ ├── test_ini.json
│ │ │ │ ├── test_jl.json
│ │ │ │ ├── test_js.json
│ │ │ │ ├── test_json.json
│ │ │ │ ├── test_jsx.json
│ │ │ │ ├── test_less.json
│ │ │ │ ├── test_log.json
│ │ │ │ ├── test_lua.json
│ │ │ │ ├── test_m.json
│ │ │ │ ├── test_md.json
│ │ │ │ ├── test_mm.json
│ │ │ │ ├── test_p6.json
│ │ │ │ ├── test_php.json
│ │ │ │ ├── test_pl.json
│ │ │ │ ├── test_ps1.json
│ │ │ │ ├── test_pug.json
│ │ │ │ ├── test_py.json
│ │ │ │ ├── test_r.json
│ │ │ │ ├── test_rb.json
│ │ │ │ ├── test_regexp.ts.json
│ │ │ │ ├── test_rs.json
│ │ │ │ ├── test_rst.json
│ │ │ │ ├── test_scss.json
│ │ │ │ ├── test_sh.json
│ │ │ │ ├── test_shader.json
│ │ │ │ ├── test_sql.json
│ │ │ │ ├── test_sty.json
│ │ │ │ ├── test_swift.json
│ │ │ │ ├── test_tex.json
│ │ │ │ ├── test_ts.json
│ │ │ │ ├── test_vb.json
│ │ │ │ ├── test_xml.json
│ │ │ │ ├── test_yaml.json
│ │ │ │ └── tsconfig_off_json.json
│ │ │ ├── colorize-tree-sitter-results/
│ │ │ │ ├── 12750_html.json
│ │ │ │ ├── 13448_html.json
│ │ │ │ ├── 14119_less.json
│ │ │ │ ├── 25920_html.json
│ │ │ │ ├── COMMIT_EDITMSG.json
│ │ │ │ ├── Dockerfile.json
│ │ │ │ ├── basic_java.json
│ │ │ │ ├── git-rebase-todo.json
│ │ │ │ ├── issue-1550_yaml.json
│ │ │ │ ├── issue-224862_yaml.json
│ │ │ │ ├── issue-28354_php.json
│ │ │ │ ├── issue-4008_yaml.json
│ │ │ │ ├── issue-6303_yaml.json
│ │ │ │ ├── issue-76997_php.json
│ │ │ │ ├── makefile.json
│ │ │ │ ├── md-math_md.json
│ │ │ │ ├── test-13777_go.json
│ │ │ │ ├── test-166781_rs.json
│ │ │ │ ├── test-173216_sh.json
│ │ │ │ ├── test-173224_sh.json
│ │ │ │ ├── test-173336_sh.json
│ │ │ │ ├── test-23630_cpp.json
│ │ │ │ ├── test-23850_cpp.json
│ │ │ │ ├── test-241001_ts.json
│ │ │ │ ├── test-33886_md.json
│ │ │ │ ├── test-4287_pug.json
│ │ │ │ ├── test-6611_rs.json
│ │ │ │ ├── test-7115_xml.json
│ │ │ │ ├── test-78769_cpp.json
│ │ │ │ ├── test-80644_cpp.json
│ │ │ │ ├── test-brackets_tsx.json
│ │ │ │ ├── test-cssvariables_less.json
│ │ │ │ ├── test-cssvariables_scss.json
│ │ │ │ ├── test-embedding_html.json
│ │ │ │ ├── test-freeze-56377_py.json
│ │ │ │ ├── test-freeze-56476_ps1.json
│ │ │ │ ├── test-function-inv_ts.json
│ │ │ │ ├── test-issue11_ts.json
│ │ │ │ ├── test-issue241715_ts.json
│ │ │ │ ├── test-issue5431_ts.json
│ │ │ │ ├── test-issue5465_ts.json
│ │ │ │ ├── test-issue5566_ts.json
│ │ │ │ ├── test-jsdoc-multiline-type_ts.json
│ │ │ │ ├── test-keywords_ts.json
│ │ │ │ ├── test-members_ts.json
│ │ │ │ ├── test-object-literals_ts.json
│ │ │ │ ├── test-regex_coffee.json
│ │ │ │ ├── test-strings_ts.json
│ │ │ │ ├── test-this_ts.json
│ │ │ │ ├── test-variables_css.json
│ │ │ │ ├── test2_pl.json
│ │ │ │ ├── test6916_js.json
│ │ │ │ ├── test_bat.json
│ │ │ │ ├── test_bib.json
│ │ │ │ ├── test_c.json
│ │ │ │ ├── test_cc.json
│ │ │ │ ├── test_clj.json
│ │ │ │ ├── test_code-snippets.json
│ │ │ │ ├── test_coffee.json
│ │ │ │ ├── test_cpp.json
│ │ │ │ ├── test_cs.json
│ │ │ │ ├── test_cshtml.json
│ │ │ │ ├── test_css.json
│ │ │ │ ├── test_cu.json
│ │ │ │ ├── test_dart.json
│ │ │ │ ├── test_diff.json
│ │ │ │ ├── test_fs.json
│ │ │ │ ├── test_go.json
│ │ │ │ ├── test_groovy.json
│ │ │ │ ├── test_handlebars.json
│ │ │ │ ├── test_hbs.json
│ │ │ │ ├── test_hlsl.json
│ │ │ │ ├── test_html.json
│ │ │ │ ├── test_ini.json
│ │ │ │ ├── test_jl.json
│ │ │ │ ├── test_js.json
│ │ │ │ ├── test_json.json
│ │ │ │ ├── test_jsx.json
│ │ │ │ ├── test_less.json
│ │ │ │ ├── test_log.json
│ │ │ │ ├── test_lua.json
│ │ │ │ ├── test_m.json
│ │ │ │ ├── test_md.json
│ │ │ │ ├── test_mm.json
│ │ │ │ ├── test_p6.json
│ │ │ │ ├── test_php.json
│ │ │ │ ├── test_pl.json
│ │ │ │ ├── test_ps1.json
│ │ │ │ ├── test_pug.json
│ │ │ │ ├── test_py.json
│ │ │ │ ├── test_r.json
│ │ │ │ ├── test_rb.json
│ │ │ │ ├── test_regexp.ts.json
│ │ │ │ ├── test_rs.json
│ │ │ │ ├── test_rst.json
│ │ │ │ ├── test_scss.json
│ │ │ │ ├── test_sh.json
│ │ │ │ ├── test_shader.json
│ │ │ │ ├── test_sql.json
│ │ │ │ ├── test_sty.json
│ │ │ │ ├── test_swift.json
│ │ │ │ ├── test_tex.json
│ │ │ │ ├── test_ts.json
│ │ │ │ ├── test_vb.json
│ │ │ │ ├── test_xml.json
│ │ │ │ ├── test_yaml.json
│ │ │ │ └── tsconfig_off_json.json
│ │ │ └── semantic-test/
│ │ │ ├── .vscode/
│ │ │ │ └── settings.json
│ │ │ └── semantic-test.json
│ │ └── tsconfig.json
│ ├── vscode-test-resolver/
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── .vscodeignore
│ │ ├── extension-browser.webpack.config.js
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── terminateProcess.sh
│ │ ├── src/
│ │ │ ├── download.ts
│ │ │ ├── extension.browser.ts
│ │ │ ├── extension.ts
│ │ │ └── util/
│ │ │ └── processes.ts
│ │ └── tsconfig.json
│ ├── xml/
│ │ ├── .vscodeignore
│ │ ├── cgmanifest.json
│ │ ├── package.json
│ │ ├── package.nls.json
│ │ ├── syntaxes/
│ │ │ ├── xml.tmLanguage.json
│ │ │ └── xsl.tmLanguage.json
│ │ ├── xml.language-configuration.json
│ │ └── xsl.language-configuration.json
│ └── yaml/
│ ├── .vscodeignore
│ ├── build/
│ │ └── update-grammar.js
│ ├── cgmanifest.json
│ ├── language-configuration.json
│ ├── package.json
│ ├── package.nls.json
│ └── syntaxes/
│ ├── yaml-1.0.tmLanguage.json
│ ├── yaml-1.1.tmLanguage.json
│ ├── yaml-1.2.tmLanguage.json
│ ├── yaml-1.3.tmLanguage.json
│ ├── yaml-embedded.tmLanguage.json
│ └── yaml.tmLanguage.json
├── gulpfile.js
├── package.json
├── product.json
├── remote/
│ ├── .npmrc
│ ├── package.json
│ └── web/
│ ├── .npmrc
│ └── package.json
├── resources/
│ ├── completions/
│ │ ├── bash/
│ │ │ └── code
│ │ └── zsh/
│ │ └── _code
│ ├── darwin/
│ │ ├── bat.icns
│ │ ├── bin/
│ │ │ └── code.sh
│ │ ├── bower.icns
│ │ ├── c.icns
│ │ ├── code.icns
│ │ ├── config.icns
│ │ ├── cpp.icns
│ │ ├── csharp.icns
│ │ ├── css.icns
│ │ ├── default.icns
│ │ ├── go.icns
│ │ ├── html.icns
│ │ ├── jade.icns
│ │ ├── java.icns
│ │ ├── javascript.icns
│ │ ├── json.icns
│ │ ├── less.icns
│ │ ├── markdown.icns
│ │ ├── php.icns
│ │ ├── powershell.icns
│ │ ├── python.icns
│ │ ├── react.icns
│ │ ├── ruby.icns
│ │ ├── sass.icns
│ │ ├── shell.icns
│ │ ├── sql.icns
│ │ ├── typescript.icns
│ │ ├── vue.icns
│ │ ├── xml.icns
│ │ └── yaml.icns
│ ├── linux/
│ │ ├── bin/
│ │ │ └── code.sh
│ │ ├── code-url-handler.desktop
│ │ ├── code-workspace.xml
│ │ ├── code.appdata.xml
│ │ ├── code.desktop
│ │ ├── debian/
│ │ │ ├── control.template
│ │ │ ├── postinst.template
│ │ │ ├── postrm.template
│ │ │ ├── prerm.template
│ │ │ └── templates.template
│ │ ├── rpm/
│ │ │ ├── code.spec.template
│ │ │ └── code.xpm
│ │ └── snap/
│ │ ├── electron-launch
│ │ └── snapcraft.yaml
│ ├── server/
│ │ ├── bin/
│ │ │ ├── code-server-darwin.sh
│ │ │ ├── code-server-linux.sh
│ │ │ ├── code-server.cmd
│ │ │ ├── helpers/
│ │ │ │ ├── browser-darwin.sh
│ │ │ │ ├── browser-linux.sh
│ │ │ │ ├── browser.cmd
│ │ │ │ └── check-requirements-linux.sh
│ │ │ └── remote-cli/
│ │ │ ├── code-darwin.sh
│ │ │ ├── code-linux.sh
│ │ │ └── code.cmd
│ │ ├── bin-dev/
│ │ │ ├── helpers/
│ │ │ │ ├── browser.cmd
│ │ │ │ └── browser.sh
│ │ │ └── remote-cli/
│ │ │ ├── code.cmd
│ │ │ └── code.sh
│ │ └── manifest.json
│ └── win32/
│ ├── VisualElementsManifest.xml
│ └── bin/
│ ├── code.cmd
│ └── code.sh
├── scripts/
│ ├── appimage/
│ │ ├── create-appimage-old.sh
│ │ ├── create_appimage.sh
│ │ ├── readme.md
│ │ ├── void-url-handler.desktop
│ │ └── void.desktop
│ ├── code-cli.bat
│ ├── code-cli.sh
│ ├── code-perf.js
│ ├── code-server.bat
│ ├── code-server.js
│ ├── code-server.sh
│ ├── code-web.bat
│ ├── code-web.js
│ ├── code-web.sh
│ ├── code.bat
│ ├── code.sh
│ ├── generate-definitelytyped.sh
│ ├── node-electron.bat
│ ├── node-electron.sh
│ ├── package.json
│ ├── playground-server.ts
│ ├── test-documentation.bat
│ ├── test-documentation.sh
│ ├── test-integration.bat
│ ├── test-integration.sh
│ ├── test-remote-integration.bat
│ ├── test-remote-integration.sh
│ ├── test-web-integration.bat
│ ├── test-web-integration.sh
│ ├── test.bat
│ ├── test.sh
│ ├── xterm-symlink.ps1
│ ├── xterm-update.js
│ └── xterm-update.ps1
├── src/
│ ├── bootstrap-cli.ts
│ ├── bootstrap-esm.ts
│ ├── bootstrap-fork.ts
│ ├── bootstrap-import.ts
│ ├── bootstrap-meta.ts
│ ├── bootstrap-node.ts
│ ├── bootstrap-server.ts
│ ├── bootstrap-window.ts
│ ├── cli.ts
│ ├── main.ts
│ ├── server-cli.ts
│ ├── server-main.ts
│ ├── tsconfig.base.json
│ ├── tsconfig.json
│ ├── tsconfig.monaco.json
│ ├── tsconfig.tsec.json
│ ├── tsconfig.vscode-dts.json
│ ├── tsconfig.vscode-proposed-dts.json
│ ├── tsec.exemptions.json
│ ├── typings/
│ │ ├── base-common.d.ts
│ │ ├── crypto.d.ts
│ │ ├── editContext.d.ts
│ │ ├── thenable.d.ts
│ │ ├── vscode-globals-nls.d.ts
│ │ ├── vscode-globals-product.d.ts
│ │ └── vscode-globals-ttp.d.ts
│ ├── vs/
│ │ ├── amdX.ts
│ │ ├── base/
│ │ │ ├── browser/
│ │ │ │ ├── broadcast.ts
│ │ │ │ ├── browser.ts
│ │ │ │ ├── canIUse.ts
│ │ │ │ ├── contextmenu.ts
│ │ │ │ ├── cssValue.ts
│ │ │ │ ├── deviceAccess.ts
│ │ │ │ ├── dnd.ts
│ │ │ │ ├── dom.ts
│ │ │ │ ├── domImpl/
│ │ │ │ │ ├── domObservable.ts
│ │ │ │ │ └── n.ts
│ │ │ │ ├── domStylesheets.ts
│ │ │ │ ├── dompurify/
│ │ │ │ │ ├── cgmanifest.json
│ │ │ │ │ ├── dompurify.d.ts
│ │ │ │ │ ├── dompurify.js
│ │ │ │ │ └── dompurify.license.txt
│ │ │ │ ├── event.ts
│ │ │ │ ├── fastDomNode.ts
│ │ │ │ ├── fonts.ts
│ │ │ │ ├── formattedTextRenderer.ts
│ │ │ │ ├── globalPointerMoveMonitor.ts
│ │ │ │ ├── history.ts
│ │ │ │ ├── iframe.ts
│ │ │ │ ├── indexedDB.ts
│ │ │ │ ├── keyboardEvent.ts
│ │ │ │ ├── markdownRenderer.ts
│ │ │ │ ├── mouseEvent.ts
│ │ │ │ ├── performance.ts
│ │ │ │ ├── pixelRatio.ts
│ │ │ │ ├── touch.ts
│ │ │ │ ├── trustedTypes.ts
│ │ │ │ ├── ui/
│ │ │ │ │ ├── actionbar/
│ │ │ │ │ │ ├── actionViewItems.ts
│ │ │ │ │ │ ├── actionbar.css
│ │ │ │ │ │ └── actionbar.ts
│ │ │ │ │ ├── aria/
│ │ │ │ │ │ ├── aria.css
│ │ │ │ │ │ └── aria.ts
│ │ │ │ │ ├── breadcrumbs/
│ │ │ │ │ │ ├── breadcrumbsWidget.css
│ │ │ │ │ │ └── breadcrumbsWidget.ts
│ │ │ │ │ ├── button/
│ │ │ │ │ │ ├── button.css
│ │ │ │ │ │ └── button.ts
│ │ │ │ │ ├── centered/
│ │ │ │ │ │ └── centeredViewLayout.ts
│ │ │ │ │ ├── codicons/
│ │ │ │ │ │ ├── codicon/
│ │ │ │ │ │ │ ├── codicon-modifiers.css
│ │ │ │ │ │ │ └── codicon.css
│ │ │ │ │ │ └── codiconStyles.ts
│ │ │ │ │ ├── contextview/
│ │ │ │ │ │ ├── contextview.css
│ │ │ │ │ │ └── contextview.ts
│ │ │ │ │ ├── countBadge/
│ │ │ │ │ │ ├── countBadge.css
│ │ │ │ │ │ └── countBadge.ts
│ │ │ │ │ ├── dialog/
│ │ │ │ │ │ ├── dialog.css
│ │ │ │ │ │ └── dialog.ts
│ │ │ │ │ ├── dnd/
│ │ │ │ │ │ ├── dnd.css
│ │ │ │ │ │ └── dnd.ts
│ │ │ │ │ ├── dropdown/
│ │ │ │ │ │ ├── dropdown.css
│ │ │ │ │ │ ├── dropdown.ts
│ │ │ │ │ │ └── dropdownActionViewItem.ts
│ │ │ │ │ ├── findinput/
│ │ │ │ │ │ ├── findInput.css
│ │ │ │ │ │ ├── findInput.ts
│ │ │ │ │ │ ├── findInputToggles.ts
│ │ │ │ │ │ └── replaceInput.ts
│ │ │ │ │ ├── grid/
│ │ │ │ │ │ ├── grid.ts
│ │ │ │ │ │ ├── gridview.css
│ │ │ │ │ │ └── gridview.ts
│ │ │ │ │ ├── highlightedlabel/
│ │ │ │ │ │ └── highlightedLabel.ts
│ │ │ │ │ ├── hover/
│ │ │ │ │ │ ├── hover.ts
│ │ │ │ │ │ ├── hoverDelegate.ts
│ │ │ │ │ │ ├── hoverDelegate2.ts
│ │ │ │ │ │ ├── hoverDelegateFactory.ts
│ │ │ │ │ │ ├── hoverWidget.css
│ │ │ │ │ │ └── hoverWidget.ts
│ │ │ │ │ ├── iconLabel/
│ │ │ │ │ │ ├── iconLabel.ts
│ │ │ │ │ │ ├── iconLabels.ts
│ │ │ │ │ │ ├── iconlabel.css
│ │ │ │ │ │ └── simpleIconLabel.ts
│ │ │ │ │ ├── icons/
│ │ │ │ │ │ ├── iconSelectBox.css
│ │ │ │ │ │ └── iconSelectBox.ts
│ │ │ │ │ ├── inputbox/
│ │ │ │ │ │ ├── inputBox.css
│ │ │ │ │ │ └── inputBox.ts
│ │ │ │ │ ├── keybindingLabel/
│ │ │ │ │ │ ├── keybindingLabel.css
│ │ │ │ │ │ └── keybindingLabel.ts
│ │ │ │ │ ├── list/
│ │ │ │ │ │ ├── list.css
│ │ │ │ │ │ ├── list.ts
│ │ │ │ │ │ ├── listPaging.ts
│ │ │ │ │ │ ├── listView.ts
│ │ │ │ │ │ ├── listWidget.ts
│ │ │ │ │ │ ├── rangeMap.ts
│ │ │ │ │ │ ├── rowCache.ts
│ │ │ │ │ │ └── splice.ts
│ │ │ │ │ ├── menu/
│ │ │ │ │ │ ├── menu.ts
│ │ │ │ │ │ ├── menubar.css
│ │ │ │ │ │ └── menubar.ts
│ │ │ │ │ ├── mouseCursor/
│ │ │ │ │ │ ├── mouseCursor.css
│ │ │ │ │ │ └── mouseCursor.ts
│ │ │ │ │ ├── progressbar/
│ │ │ │ │ │ ├── progressAccessibilitySignal.ts
│ │ │ │ │ │ ├── progressbar.css
│ │ │ │ │ │ └── progressbar.ts
│ │ │ │ │ ├── radio/
│ │ │ │ │ │ ├── radio.css
│ │ │ │ │ │ └── radio.ts
│ │ │ │ │ ├── resizable/
│ │ │ │ │ │ └── resizable.ts
│ │ │ │ │ ├── sash/
│ │ │ │ │ │ ├── sash.css
│ │ │ │ │ │ └── sash.ts
│ │ │ │ │ ├── scrollbar/
│ │ │ │ │ │ ├── abstractScrollbar.ts
│ │ │ │ │ │ ├── horizontalScrollbar.ts
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── scrollbars.css
│ │ │ │ │ │ ├── scrollableElement.ts
│ │ │ │ │ │ ├── scrollableElementOptions.ts
│ │ │ │ │ │ ├── scrollbarArrow.ts
│ │ │ │ │ │ ├── scrollbarState.ts
│ │ │ │ │ │ ├── scrollbarVisibilityController.ts
│ │ │ │ │ │ └── verticalScrollbar.ts
│ │ │ │ │ ├── selectBox/
│ │ │ │ │ │ ├── selectBox.css
│ │ │ │ │ │ ├── selectBox.ts
│ │ │ │ │ │ ├── selectBoxCustom.css
│ │ │ │ │ │ ├── selectBoxCustom.ts
│ │ │ │ │ │ └── selectBoxNative.ts
│ │ │ │ │ ├── severityIcon/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── severityIcon.css
│ │ │ │ │ │ └── severityIcon.ts
│ │ │ │ │ ├── splitview/
│ │ │ │ │ │ ├── paneview.css
│ │ │ │ │ │ ├── paneview.ts
│ │ │ │ │ │ ├── splitview.css
│ │ │ │ │ │ └── splitview.ts
│ │ │ │ │ ├── table/
│ │ │ │ │ │ ├── table.css
│ │ │ │ │ │ ├── table.ts
│ │ │ │ │ │ └── tableWidget.ts
│ │ │ │ │ ├── toggle/
│ │ │ │ │ │ ├── toggle.css
│ │ │ │ │ │ └── toggle.ts
│ │ │ │ │ ├── toolbar/
│ │ │ │ │ │ ├── toolbar.css
│ │ │ │ │ │ └── toolbar.ts
│ │ │ │ │ ├── tree/
│ │ │ │ │ │ ├── abstractTree.ts
│ │ │ │ │ │ ├── asyncDataTree.ts
│ │ │ │ │ │ ├── compressedObjectTreeModel.ts
│ │ │ │ │ │ ├── dataTree.ts
│ │ │ │ │ │ ├── indexTree.ts
│ │ │ │ │ │ ├── indexTreeModel.ts
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ ├── paneviewlet.css
│ │ │ │ │ │ │ └── tree.css
│ │ │ │ │ │ ├── objectTree.ts
│ │ │ │ │ │ ├── objectTreeModel.ts
│ │ │ │ │ │ ├── tree.ts
│ │ │ │ │ │ └── treeDefaults.ts
│ │ │ │ │ └── widget.ts
│ │ │ │ ├── webWorkerFactory.ts
│ │ │ │ └── window.ts
│ │ │ ├── common/
│ │ │ │ ├── actions.ts
│ │ │ │ ├── arrays.ts
│ │ │ │ ├── arraysFind.ts
│ │ │ │ ├── assert.ts
│ │ │ │ ├── async.ts
│ │ │ │ ├── buffer.ts
│ │ │ │ ├── cache.ts
│ │ │ │ ├── cancellation.ts
│ │ │ │ ├── charCode.ts
│ │ │ │ ├── codecs/
│ │ │ │ │ ├── asyncDecoder.ts
│ │ │ │ │ ├── baseDecoder.ts
│ │ │ │ │ └── types/
│ │ │ │ │ └── ICodec.d.ts
│ │ │ │ ├── codicons.ts
│ │ │ │ ├── codiconsLibrary.ts
│ │ │ │ ├── codiconsUtil.ts
│ │ │ │ ├── collections.ts
│ │ │ │ ├── color.ts
│ │ │ │ ├── comparers.ts
│ │ │ │ ├── console.ts
│ │ │ │ ├── controlFlow.ts
│ │ │ │ ├── dataTransfer.ts
│ │ │ │ ├── date.ts
│ │ │ │ ├── decorators/
│ │ │ │ │ └── cancelPreviousCalls.ts
│ │ │ │ ├── decorators.ts
│ │ │ │ ├── desktopEnvironmentInfo.ts
│ │ │ │ ├── diff/
│ │ │ │ │ ├── diff.ts
│ │ │ │ │ └── diffChange.ts
│ │ │ │ ├── envfile.ts
│ │ │ │ ├── equals.ts
│ │ │ │ ├── errorMessage.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── event.ts
│ │ │ │ ├── extpath.ts
│ │ │ │ ├── filters.ts
│ │ │ │ ├── functional.ts
│ │ │ │ ├── fuzzyScorer.ts
│ │ │ │ ├── glob.ts
│ │ │ │ ├── hash.ts
│ │ │ │ ├── hierarchicalKind.ts
│ │ │ │ ├── history.ts
│ │ │ │ ├── hotReload.ts
│ │ │ │ ├── hotReloadHelpers.ts
│ │ │ │ ├── htmlContent.ts
│ │ │ │ ├── iconLabels.ts
│ │ │ │ ├── idGenerator.ts
│ │ │ │ ├── ime.ts
│ │ │ │ ├── iterator.ts
│ │ │ │ ├── json.ts
│ │ │ │ ├── jsonEdit.ts
│ │ │ │ ├── jsonErrorMessages.ts
│ │ │ │ ├── jsonFormatter.ts
│ │ │ │ ├── jsonSchema.ts
│ │ │ │ ├── jsonc.ts
│ │ │ │ ├── keyCodes.ts
│ │ │ │ ├── keybindingLabels.ts
│ │ │ │ ├── keybindingParser.ts
│ │ │ │ ├── keybindings.ts
│ │ │ │ ├── labels.ts
│ │ │ │ ├── lazy.ts
│ │ │ │ ├── lifecycle.ts
│ │ │ │ ├── linkedList.ts
│ │ │ │ ├── linkedText.ts
│ │ │ │ ├── map.ts
│ │ │ │ ├── marked/
│ │ │ │ │ ├── cgmanifest.json
│ │ │ │ │ ├── marked.d.ts
│ │ │ │ │ ├── marked.js
│ │ │ │ │ └── marked.license.txt
│ │ │ │ ├── marshalling.ts
│ │ │ │ ├── marshallingIds.ts
│ │ │ │ ├── mime.ts
│ │ │ │ ├── naturalLanguage/
│ │ │ │ │ └── korean.ts
│ │ │ │ ├── navigator.ts
│ │ │ │ ├── network.ts
│ │ │ │ ├── normalization.ts
│ │ │ │ ├── numbers.ts
│ │ │ │ ├── objectCache.ts
│ │ │ │ ├── objects.ts
│ │ │ │ ├── observable.ts
│ │ │ │ ├── observableDisposable.ts
│ │ │ │ ├── observableInternal/
│ │ │ │ │ ├── api.ts
│ │ │ │ │ ├── autorun.ts
│ │ │ │ │ ├── base.ts
│ │ │ │ │ ├── commonFacade/
│ │ │ │ │ │ ├── cancellation.ts
│ │ │ │ │ │ └── deps.ts
│ │ │ │ │ ├── debugName.ts
│ │ │ │ │ ├── derived.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── lazyObservableValue.ts
│ │ │ │ │ ├── logging/
│ │ │ │ │ │ ├── consoleObservableLogger.ts
│ │ │ │ │ │ ├── debugger/
│ │ │ │ │ │ │ ├── debuggerApi.d.ts
│ │ │ │ │ │ │ ├── debuggerRpc.ts
│ │ │ │ │ │ │ ├── devToolsLogger.ts
│ │ │ │ │ │ │ ├── rpc.ts
│ │ │ │ │ │ │ └── utils.ts
│ │ │ │ │ │ └── logging.ts
│ │ │ │ │ ├── promise.ts
│ │ │ │ │ ├── utils.ts
│ │ │ │ │ └── utilsCancellation.ts
│ │ │ │ ├── paging.ts
│ │ │ │ ├── parsers.ts
│ │ │ │ ├── path.ts
│ │ │ │ ├── performance.ts
│ │ │ │ ├── platform.ts
│ │ │ │ ├── policy.ts
│ │ │ │ ├── ports.ts
│ │ │ │ ├── prefixTree.ts
│ │ │ │ ├── process.ts
│ │ │ │ ├── processes.ts
│ │ │ │ ├── product.ts
│ │ │ │ ├── range.ts
│ │ │ │ ├── resourceTree.ts
│ │ │ │ ├── resources.ts
│ │ │ │ ├── scrollable.ts
│ │ │ │ ├── search.ts
│ │ │ │ ├── semver/
│ │ │ │ │ ├── cgmanifest.json
│ │ │ │ │ ├── semver.d.ts
│ │ │ │ │ └── semver.js
│ │ │ │ ├── sequence.ts
│ │ │ │ ├── severity.ts
│ │ │ │ ├── skipList.ts
│ │ │ │ ├── stopwatch.ts
│ │ │ │ ├── stream.ts
│ │ │ │ ├── strings.ts
│ │ │ │ ├── symbols.ts
│ │ │ │ ├── ternarySearchTree.ts
│ │ │ │ ├── tfIdf.ts
│ │ │ │ ├── themables.ts
│ │ │ │ ├── types.ts
│ │ │ │ ├── uint.ts
│ │ │ │ ├── uri.ts
│ │ │ │ ├── uriIpc.ts
│ │ │ │ ├── uuid.ts
│ │ │ │ ├── verifier.ts
│ │ │ │ └── worker/
│ │ │ │ ├── webWorker.ts
│ │ │ │ └── webWorkerBootstrap.ts
│ │ │ ├── node/
│ │ │ │ ├── cpuUsage.sh
│ │ │ │ ├── crypto.ts
│ │ │ │ ├── extpath.ts
│ │ │ │ ├── id.ts
│ │ │ │ ├── macAddress.ts
│ │ │ │ ├── nls.ts
│ │ │ │ ├── nodeStreams.ts
│ │ │ │ ├── osDisplayProtocolInfo.ts
│ │ │ │ ├── osReleaseInfo.ts
│ │ │ │ ├── pfs.ts
│ │ │ │ ├── ports.ts
│ │ │ │ ├── powershell.ts
│ │ │ │ ├── processes.ts
│ │ │ │ ├── ps.sh
│ │ │ │ ├── ps.ts
│ │ │ │ ├── shell.ts
│ │ │ │ ├── terminalEncoding.ts
│ │ │ │ ├── terminateProcess.sh
│ │ │ │ ├── unc.ts
│ │ │ │ └── zip.ts
│ │ │ ├── parts/
│ │ │ │ ├── contextmenu/
│ │ │ │ │ ├── common/
│ │ │ │ │ │ └── contextmenu.ts
│ │ │ │ │ ├── electron-main/
│ │ │ │ │ │ └── contextmenu.ts
│ │ │ │ │ └── electron-sandbox/
│ │ │ │ │ └── contextmenu.ts
│ │ │ │ ├── ipc/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── ipc.mp.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── ipc.electron.ts
│ │ │ │ │ │ ├── ipc.mp.ts
│ │ │ │ │ │ ├── ipc.net.ts
│ │ │ │ │ │ └── ipc.ts
│ │ │ │ │ ├── electron-main/
│ │ │ │ │ │ ├── ipc.electron.ts
│ │ │ │ │ │ ├── ipc.mp.ts
│ │ │ │ │ │ └── ipcMain.ts
│ │ │ │ │ ├── electron-sandbox/
│ │ │ │ │ │ ├── ipc.electron.ts
│ │ │ │ │ │ └── ipc.mp.ts
│ │ │ │ │ ├── node/
│ │ │ │ │ │ ├── ipc.cp.ts
│ │ │ │ │ │ ├── ipc.mp.ts
│ │ │ │ │ │ └── ipc.net.ts
│ │ │ │ │ └── test/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── ipc.mp.test.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ └── ipc.test.ts
│ │ │ │ │ ├── electron-sandbox/
│ │ │ │ │ │ └── ipc.mp.test.ts
│ │ │ │ │ └── node/
│ │ │ │ │ ├── ipc.cp.integrationTest.ts
│ │ │ │ │ ├── ipc.net.test.ts
│ │ │ │ │ ├── testApp.ts
│ │ │ │ │ └── testService.ts
│ │ │ │ ├── request/
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── request.ts
│ │ │ │ │ │ └── requestImpl.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── electron-main/
│ │ │ │ │ └── request.test.ts
│ │ │ │ ├── sandbox/
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── electronTypes.ts
│ │ │ │ │ │ └── sandboxTypes.ts
│ │ │ │ │ ├── electron-sandbox/
│ │ │ │ │ │ ├── electronTypes.ts
│ │ │ │ │ │ ├── globals.ts
│ │ │ │ │ │ ├── preload-aux.ts
│ │ │ │ │ │ └── preload.ts
│ │ │ │ │ ├── node/
│ │ │ │ │ │ └── electronTypes.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── electron-sandbox/
│ │ │ │ │ └── globals.test.ts
│ │ │ │ └── storage/
│ │ │ │ ├── common/
│ │ │ │ │ └── storage.ts
│ │ │ │ ├── node/
│ │ │ │ │ └── storage.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ └── storage.integrationTest.ts
│ │ │ └── test/
│ │ │ ├── browser/
│ │ │ │ ├── actionbar.test.ts
│ │ │ │ ├── browser.test.ts
│ │ │ │ ├── comparers.test.ts
│ │ │ │ ├── dom.test.ts
│ │ │ │ ├── formattedTextRenderer.test.ts
│ │ │ │ ├── hash.test.ts
│ │ │ │ ├── highlightedLabel.test.ts
│ │ │ │ ├── iconLabels.test.ts
│ │ │ │ ├── indexedDB.test.ts
│ │ │ │ ├── markdownRenderer.test.ts
│ │ │ │ ├── progressBar.test.ts
│ │ │ │ └── ui/
│ │ │ │ ├── contextview/
│ │ │ │ │ └── contextview.test.ts
│ │ │ │ ├── grid/
│ │ │ │ │ ├── grid.test.ts
│ │ │ │ │ ├── gridview.test.ts
│ │ │ │ │ └── util.ts
│ │ │ │ ├── list/
│ │ │ │ │ ├── listView.test.ts
│ │ │ │ │ ├── listWidget.test.ts
│ │ │ │ │ └── rangeMap.test.ts
│ │ │ │ ├── menu/
│ │ │ │ │ └── menubar.test.ts
│ │ │ │ ├── scrollbar/
│ │ │ │ │ ├── scrollableElement.test.ts
│ │ │ │ │ └── scrollbarState.test.ts
│ │ │ │ ├── splitview/
│ │ │ │ │ └── splitview.test.ts
│ │ │ │ └── tree/
│ │ │ │ ├── asyncDataTree.test.ts
│ │ │ │ ├── compressedObjectTreeModel.test.ts
│ │ │ │ ├── dataTree.test.ts
│ │ │ │ ├── indexTreeModel.test.ts
│ │ │ │ ├── objectTree.test.ts
│ │ │ │ └── objectTreeModel.test.ts
│ │ │ ├── common/
│ │ │ │ ├── arrays.test.ts
│ │ │ │ ├── arraysFind.test.ts
│ │ │ │ ├── assert.test.ts
│ │ │ │ ├── assertHeap.ts
│ │ │ │ ├── async.test.ts
│ │ │ │ ├── buffer.test.ts
│ │ │ │ ├── cache.test.ts
│ │ │ │ ├── cancelPreviousCalls.test.ts
│ │ │ │ ├── cancellation.test.ts
│ │ │ │ ├── charCode.test.ts
│ │ │ │ ├── collections.test.ts
│ │ │ │ ├── color.test.ts
│ │ │ │ ├── console.test.ts
│ │ │ │ ├── date.test.ts
│ │ │ │ ├── decorators.test.ts
│ │ │ │ ├── diff/
│ │ │ │ │ └── diff.test.ts
│ │ │ │ ├── envfile.test.ts
│ │ │ │ ├── errors.test.ts
│ │ │ │ ├── event.test.ts
│ │ │ │ ├── extpath.test.ts
│ │ │ │ ├── filters.perf.data.d.ts
│ │ │ │ ├── filters.perf.data.js
│ │ │ │ ├── filters.perf.test.ts
│ │ │ │ ├── filters.test.ts
│ │ │ │ ├── fuzzyScorer.test.ts
│ │ │ │ ├── glob.test.ts
│ │ │ │ ├── history.test.ts
│ │ │ │ ├── iconLabels.test.ts
│ │ │ │ ├── iterator.test.ts
│ │ │ │ ├── json.test.ts
│ │ │ │ ├── jsonEdit.test.ts
│ │ │ │ ├── jsonFormatter.test.ts
│ │ │ │ ├── jsonParse.test.ts
│ │ │ │ ├── jsonSchema.test.ts
│ │ │ │ ├── keyCodes.test.ts
│ │ │ │ ├── keybindings.test.ts
│ │ │ │ ├── labels.test.ts
│ │ │ │ ├── lazy.test.ts
│ │ │ │ ├── lifecycle.test.ts
│ │ │ │ ├── linkedList.test.ts
│ │ │ │ ├── linkedText.test.ts
│ │ │ │ ├── map.test.ts
│ │ │ │ ├── markdownString.test.ts
│ │ │ │ ├── marshalling.test.ts
│ │ │ │ ├── mime.test.ts
│ │ │ │ ├── mock.ts
│ │ │ │ ├── naturalLanguage/
│ │ │ │ │ └── korean.test.ts
│ │ │ │ ├── network.test.ts
│ │ │ │ ├── normalization.test.ts
│ │ │ │ ├── numbers.test.ts
│ │ │ │ ├── objectCache.test.ts
│ │ │ │ ├── objects.test.ts
│ │ │ │ ├── observable.test.ts
│ │ │ │ ├── observableDisposable.test.ts
│ │ │ │ ├── paging.test.ts
│ │ │ │ ├── path.test.ts
│ │ │ │ ├── prefixTree.test.ts
│ │ │ │ ├── processes.test.ts
│ │ │ │ ├── resourceTree.test.ts
│ │ │ │ ├── resources.test.ts
│ │ │ │ ├── scrollable.test.ts
│ │ │ │ ├── skipList.test.ts
│ │ │ │ ├── snapshot.ts
│ │ │ │ ├── stream.test.ts
│ │ │ │ ├── strings.test.ts
│ │ │ │ ├── ternarySearchtree.test.ts
│ │ │ │ ├── testUtils.ts
│ │ │ │ ├── tfIdf.test.ts
│ │ │ │ ├── timeTravelScheduler.ts
│ │ │ │ ├── troubleshooting.ts
│ │ │ │ ├── types.test.ts
│ │ │ │ ├── uri.test.ts
│ │ │ │ ├── utils.ts
│ │ │ │ └── uuid.test.ts
│ │ │ └── node/
│ │ │ ├── __snapshots__/
│ │ │ │ ├── snapshot_cleans_up_old_snapshots.0.snap
│ │ │ │ ├── snapshot_cleans_up_old_snapshots.1.snap
│ │ │ │ ├── snapshot_creates_a_snapshot.0.snap
│ │ │ │ └── snapshot_formats_object_nicely.0.snap
│ │ │ ├── crypto.test.ts
│ │ │ ├── extpath.test.ts
│ │ │ ├── id.test.ts
│ │ │ ├── nodeStreams.test.ts
│ │ │ ├── pfs/
│ │ │ │ ├── fixtures/
│ │ │ │ │ ├── examples/
│ │ │ │ │ │ ├── company.jxs
│ │ │ │ │ │ ├── conway.jxs
│ │ │ │ │ │ ├── employee.jxs
│ │ │ │ │ │ └── small.jxs
│ │ │ │ │ ├── index.html
│ │ │ │ │ └── site.css
│ │ │ │ └── pfs.test.ts
│ │ │ ├── port.test.ts
│ │ │ ├── powershell.test.ts
│ │ │ ├── processes/
│ │ │ │ ├── fixtures/
│ │ │ │ │ ├── fork.ts
│ │ │ │ │ └── fork_large.ts
│ │ │ │ └── processes.integrationTest.ts
│ │ │ ├── snapshot.test.ts
│ │ │ ├── testUtils.ts
│ │ │ ├── unc.test.ts
│ │ │ ├── uri.perf.data.txt
│ │ │ ├── uri.perf.test.ts
│ │ │ ├── uri.test.data.txt
│ │ │ └── zip/
│ │ │ └── zip.test.ts
│ │ ├── code/
│ │ │ ├── browser/
│ │ │ │ └── workbench/
│ │ │ │ ├── callback.html
│ │ │ │ ├── workbench-dev.html
│ │ │ │ ├── workbench.html
│ │ │ │ └── workbench.ts
│ │ │ ├── electron-main/
│ │ │ │ ├── app.ts
│ │ │ │ └── main.ts
│ │ │ ├── electron-sandbox/
│ │ │ │ ├── processExplorer/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── processExplorer.css
│ │ │ │ │ ├── processExplorer-dev.html
│ │ │ │ │ ├── processExplorer.html
│ │ │ │ │ ├── processExplorer.ts
│ │ │ │ │ └── processExplorerMain.ts
│ │ │ │ └── workbench/
│ │ │ │ ├── workbench-dev.html
│ │ │ │ ├── workbench.html
│ │ │ │ └── workbench.ts
│ │ │ ├── electron-utility/
│ │ │ │ └── sharedProcess/
│ │ │ │ ├── contrib/
│ │ │ │ │ ├── codeCacheCleaner.ts
│ │ │ │ │ ├── defaultExtensionsInitializer.ts
│ │ │ │ │ ├── extensions.ts
│ │ │ │ │ ├── languagePackCachedDataCleaner.ts
│ │ │ │ │ ├── localizationsUpdater.ts
│ │ │ │ │ ├── logsDataCleaner.ts
│ │ │ │ │ ├── storageDataCleaner.ts
│ │ │ │ │ └── userDataProfilesCleaner.ts
│ │ │ │ └── sharedProcessMain.ts
│ │ │ └── node/
│ │ │ ├── cli.ts
│ │ │ └── cliProcessMain.ts
│ │ ├── editor/
│ │ │ ├── browser/
│ │ │ │ ├── config/
│ │ │ │ │ ├── charWidthReader.ts
│ │ │ │ │ ├── domFontInfo.ts
│ │ │ │ │ ├── editorConfiguration.ts
│ │ │ │ │ ├── elementSizeObserver.ts
│ │ │ │ │ ├── fontMeasurements.ts
│ │ │ │ │ ├── migrateOptions.ts
│ │ │ │ │ └── tabFocus.ts
│ │ │ │ ├── controller/
│ │ │ │ │ ├── editContext/
│ │ │ │ │ │ ├── clipboardUtils.ts
│ │ │ │ │ │ ├── editContext.ts
│ │ │ │ │ │ ├── native/
│ │ │ │ │ │ │ ├── debugEditContext.ts
│ │ │ │ │ │ │ ├── editContextFactory.ts
│ │ │ │ │ │ │ ├── nativeEditContext.css
│ │ │ │ │ │ │ ├── nativeEditContext.ts
│ │ │ │ │ │ │ ├── nativeEditContextRegistry.ts
│ │ │ │ │ │ │ ├── nativeEditContextUtils.ts
│ │ │ │ │ │ │ └── screenReaderSupport.ts
│ │ │ │ │ │ ├── screenReaderUtils.ts
│ │ │ │ │ │ └── textArea/
│ │ │ │ │ │ ├── textAreaEditContext.css
│ │ │ │ │ │ ├── textAreaEditContext.ts
│ │ │ │ │ │ ├── textAreaEditContextInput.ts
│ │ │ │ │ │ └── textAreaEditContextState.ts
│ │ │ │ │ ├── mouseHandler.ts
│ │ │ │ │ ├── mouseTarget.ts
│ │ │ │ │ └── pointerHandler.ts
│ │ │ │ ├── coreCommands.ts
│ │ │ │ ├── dnd.ts
│ │ │ │ ├── editorBrowser.ts
│ │ │ │ ├── editorDom.ts
│ │ │ │ ├── editorExtensions.ts
│ │ │ │ ├── gpu/
│ │ │ │ │ ├── atlas/
│ │ │ │ │ │ ├── atlas.ts
│ │ │ │ │ │ ├── textureAtlas.ts
│ │ │ │ │ │ ├── textureAtlasPage.ts
│ │ │ │ │ │ ├── textureAtlasShelfAllocator.ts
│ │ │ │ │ │ └── textureAtlasSlabAllocator.ts
│ │ │ │ │ ├── bufferDirtyTracker.ts
│ │ │ │ │ ├── contentSegmenter.ts
│ │ │ │ │ ├── css/
│ │ │ │ │ │ ├── decorationCssRuleExtractor.ts
│ │ │ │ │ │ ├── decorationStyleCache.ts
│ │ │ │ │ │ └── media/
│ │ │ │ │ │ └── decorationCssRuleExtractor.css
│ │ │ │ │ ├── gpu.ts
│ │ │ │ │ ├── gpuDisposable.ts
│ │ │ │ │ ├── gpuUtils.ts
│ │ │ │ │ ├── objectCollectionBuffer.ts
│ │ │ │ │ ├── raster/
│ │ │ │ │ │ ├── glyphRasterizer.ts
│ │ │ │ │ │ └── raster.ts
│ │ │ │ │ ├── rectangleRenderer.ts
│ │ │ │ │ ├── rectangleRenderer.wgsl.ts
│ │ │ │ │ ├── renderStrategy/
│ │ │ │ │ │ ├── baseRenderStrategy.ts
│ │ │ │ │ │ ├── fullFileRenderStrategy.ts
│ │ │ │ │ │ ├── fullFileRenderStrategy.wgsl.ts
│ │ │ │ │ │ └── viewportRenderStrategy.ts
│ │ │ │ │ ├── taskQueue.ts
│ │ │ │ │ └── viewGpuContext.ts
│ │ │ │ ├── observableCodeEditor.ts
│ │ │ │ ├── point.ts
│ │ │ │ ├── rect.ts
│ │ │ │ ├── services/
│ │ │ │ │ ├── abstractCodeEditorService.ts
│ │ │ │ │ ├── bulkEditService.ts
│ │ │ │ │ ├── codeEditorService.ts
│ │ │ │ │ ├── editorWorkerService.ts
│ │ │ │ │ ├── hoverService/
│ │ │ │ │ │ ├── hover.css
│ │ │ │ │ │ ├── hoverService.ts
│ │ │ │ │ │ ├── hoverWidget.ts
│ │ │ │ │ │ └── updatableHoverWidget.ts
│ │ │ │ │ ├── markerDecorations.ts
│ │ │ │ │ └── openerService.ts
│ │ │ │ ├── stableEditorScroll.ts
│ │ │ │ ├── view/
│ │ │ │ │ ├── domLineBreaksComputer.ts
│ │ │ │ │ ├── dynamicViewOverlay.ts
│ │ │ │ │ ├── renderingContext.ts
│ │ │ │ │ ├── viewController.ts
│ │ │ │ │ ├── viewLayer.ts
│ │ │ │ │ ├── viewOverlays.ts
│ │ │ │ │ ├── viewPart.ts
│ │ │ │ │ └── viewUserInputEvents.ts
│ │ │ │ ├── view.ts
│ │ │ │ ├── viewParts/
│ │ │ │ │ ├── blockDecorations/
│ │ │ │ │ │ ├── blockDecorations.css
│ │ │ │ │ │ └── blockDecorations.ts
│ │ │ │ │ ├── contentWidgets/
│ │ │ │ │ │ └── contentWidgets.ts
│ │ │ │ │ ├── currentLineHighlight/
│ │ │ │ │ │ ├── currentLineHighlight.css
│ │ │ │ │ │ └── currentLineHighlight.ts
│ │ │ │ │ ├── decorations/
│ │ │ │ │ │ ├── decorations.css
│ │ │ │ │ │ └── decorations.ts
│ │ │ │ │ ├── editorScrollbar/
│ │ │ │ │ │ └── editorScrollbar.ts
│ │ │ │ │ ├── glyphMargin/
│ │ │ │ │ │ ├── glyphMargin.css
│ │ │ │ │ │ └── glyphMargin.ts
│ │ │ │ │ ├── gpuMark/
│ │ │ │ │ │ ├── gpuMark.css
│ │ │ │ │ │ └── gpuMark.ts
│ │ │ │ │ ├── indentGuides/
│ │ │ │ │ │ ├── indentGuides.css
│ │ │ │ │ │ └── indentGuides.ts
│ │ │ │ │ ├── lineNumbers/
│ │ │ │ │ │ ├── lineNumbers.css
│ │ │ │ │ │ └── lineNumbers.ts
│ │ │ │ │ ├── linesDecorations/
│ │ │ │ │ │ ├── linesDecorations.css
│ │ │ │ │ │ └── linesDecorations.ts
│ │ │ │ │ ├── margin/
│ │ │ │ │ │ ├── margin.css
│ │ │ │ │ │ └── margin.ts
│ │ │ │ │ ├── marginDecorations/
│ │ │ │ │ │ ├── marginDecorations.css
│ │ │ │ │ │ └── marginDecorations.ts
│ │ │ │ │ ├── minimap/
│ │ │ │ │ │ ├── minimap.css
│ │ │ │ │ │ ├── minimap.ts
│ │ │ │ │ │ ├── minimapCharRenderer.ts
│ │ │ │ │ │ ├── minimapCharRendererFactory.ts
│ │ │ │ │ │ ├── minimapCharSheet.ts
│ │ │ │ │ │ └── minimapPreBaked.ts
│ │ │ │ │ ├── overlayWidgets/
│ │ │ │ │ │ ├── overlayWidgets.css
│ │ │ │ │ │ └── overlayWidgets.ts
│ │ │ │ │ ├── overviewRuler/
│ │ │ │ │ │ ├── decorationsOverviewRuler.ts
│ │ │ │ │ │ └── overviewRuler.ts
│ │ │ │ │ ├── rulers/
│ │ │ │ │ │ ├── rulers.css
│ │ │ │ │ │ └── rulers.ts
│ │ │ │ │ ├── rulersGpu/
│ │ │ │ │ │ └── rulersGpu.ts
│ │ │ │ │ ├── scrollDecoration/
│ │ │ │ │ │ ├── scrollDecoration.css
│ │ │ │ │ │ └── scrollDecoration.ts
│ │ │ │ │ ├── selections/
│ │ │ │ │ │ ├── selections.css
│ │ │ │ │ │ └── selections.ts
│ │ │ │ │ ├── viewCursors/
│ │ │ │ │ │ ├── viewCursor.ts
│ │ │ │ │ │ ├── viewCursors.css
│ │ │ │ │ │ └── viewCursors.ts
│ │ │ │ │ ├── viewLines/
│ │ │ │ │ │ ├── domReadingContext.ts
│ │ │ │ │ │ ├── rangeUtil.ts
│ │ │ │ │ │ ├── viewLine.ts
│ │ │ │ │ │ ├── viewLineOptions.ts
│ │ │ │ │ │ ├── viewLines.css
│ │ │ │ │ │ └── viewLines.ts
│ │ │ │ │ ├── viewLinesGpu/
│ │ │ │ │ │ └── viewLinesGpu.ts
│ │ │ │ │ ├── viewZones/
│ │ │ │ │ │ └── viewZones.ts
│ │ │ │ │ └── whitespace/
│ │ │ │ │ ├── whitespace.css
│ │ │ │ │ └── whitespace.ts
│ │ │ │ └── widget/
│ │ │ │ ├── codeEditor/
│ │ │ │ │ ├── codeEditorContributions.ts
│ │ │ │ │ ├── codeEditorWidget.ts
│ │ │ │ │ ├── editor.css
│ │ │ │ │ └── embeddedCodeEditorWidget.ts
│ │ │ │ ├── diffEditor/
│ │ │ │ │ ├── commands.ts
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── accessibleDiffViewer.css
│ │ │ │ │ │ ├── accessibleDiffViewer.ts
│ │ │ │ │ │ ├── diffEditorDecorations.ts
│ │ │ │ │ │ ├── diffEditorEditors.ts
│ │ │ │ │ │ ├── diffEditorSash.ts
│ │ │ │ │ │ └── diffEditorViewZones/
│ │ │ │ │ │ ├── diffEditorViewZones.ts
│ │ │ │ │ │ ├── inlineDiffDeletedCodeMargin.ts
│ │ │ │ │ │ └── renderLines.ts
│ │ │ │ │ ├── delegatingEditorImpl.ts
│ │ │ │ │ ├── diffEditor.contribution.ts
│ │ │ │ │ ├── diffEditorOptions.ts
│ │ │ │ │ ├── diffEditorViewModel.ts
│ │ │ │ │ ├── diffEditorWidget.ts
│ │ │ │ │ ├── diffProviderFactoryService.ts
│ │ │ │ │ ├── embeddedDiffEditorWidget.ts
│ │ │ │ │ ├── features/
│ │ │ │ │ │ ├── gutterFeature.ts
│ │ │ │ │ │ ├── hideUnchangedRegionsFeature.ts
│ │ │ │ │ │ ├── movedBlocksLinesFeature.ts
│ │ │ │ │ │ ├── overviewRulerFeature.ts
│ │ │ │ │ │ └── revertButtonsFeature.ts
│ │ │ │ │ ├── registrations.contribution.ts
│ │ │ │ │ ├── style.css
│ │ │ │ │ ├── utils/
│ │ │ │ │ │ └── editorGutter.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── markdownRenderer/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── markdownRenderer.ts
│ │ │ │ │ └── renderedMarkdown.css
│ │ │ │ └── multiDiffEditor/
│ │ │ │ ├── colors.ts
│ │ │ │ ├── diffEditorItemTemplate.ts
│ │ │ │ ├── model.ts
│ │ │ │ ├── multiDiffEditorViewModel.ts
│ │ │ │ ├── multiDiffEditorWidget.ts
│ │ │ │ ├── multiDiffEditorWidgetImpl.ts
│ │ │ │ ├── objectPool.ts
│ │ │ │ ├── style.css
│ │ │ │ ├── utils.ts
│ │ │ │ └── workbenchUIElementFactory.ts
│ │ │ ├── common/
│ │ │ │ ├── codecs/
│ │ │ │ │ ├── baseToken.ts
│ │ │ │ │ ├── linesCodec/
│ │ │ │ │ │ ├── linesDecoder.ts
│ │ │ │ │ │ └── tokens/
│ │ │ │ │ │ ├── carriageReturn.ts
│ │ │ │ │ │ ├── line.ts
│ │ │ │ │ │ └── newLine.ts
│ │ │ │ │ ├── markdownCodec/
│ │ │ │ │ │ ├── markdownDecoder.ts
│ │ │ │ │ │ ├── parsers/
│ │ │ │ │ │ │ ├── markdownComment.ts
│ │ │ │ │ │ │ ├── markdownImage.ts
│ │ │ │ │ │ │ └── markdownLink.ts
│ │ │ │ │ │ └── tokens/
│ │ │ │ │ │ ├── markdownComment.ts
│ │ │ │ │ │ ├── markdownImage.ts
│ │ │ │ │ │ ├── markdownLink.ts
│ │ │ │ │ │ └── markdownToken.ts
│ │ │ │ │ └── simpleCodec/
│ │ │ │ │ ├── parserBase.ts
│ │ │ │ │ ├── simpleDecoder.ts
│ │ │ │ │ └── tokens/
│ │ │ │ │ ├── angleBrackets.ts
│ │ │ │ │ ├── brackets.ts
│ │ │ │ │ ├── colon.ts
│ │ │ │ │ ├── dash.ts
│ │ │ │ │ ├── exclamationMark.ts
│ │ │ │ │ ├── formFeed.ts
│ │ │ │ │ ├── hash.ts
│ │ │ │ │ ├── parentheses.ts
│ │ │ │ │ ├── space.ts
│ │ │ │ │ ├── tab.ts
│ │ │ │ │ ├── verticalTab.ts
│ │ │ │ │ └── word.ts
│ │ │ │ ├── commands/
│ │ │ │ │ ├── replaceCommand.ts
│ │ │ │ │ ├── shiftCommand.ts
│ │ │ │ │ ├── surroundSelectionCommand.ts
│ │ │ │ │ └── trimTrailingWhitespaceCommand.ts
│ │ │ │ ├── config/
│ │ │ │ │ ├── diffEditor.ts
│ │ │ │ │ ├── editorConfiguration.ts
│ │ │ │ │ ├── editorConfigurationSchema.ts
│ │ │ │ │ ├── editorOptions.ts
│ │ │ │ │ ├── editorZoom.ts
│ │ │ │ │ └── fontInfo.ts
│ │ │ │ ├── core/
│ │ │ │ │ ├── characterClassifier.ts
│ │ │ │ │ ├── cursorColumns.ts
│ │ │ │ │ ├── dimension.ts
│ │ │ │ │ ├── editOperation.ts
│ │ │ │ │ ├── editorColorRegistry.ts
│ │ │ │ │ ├── eolCounter.ts
│ │ │ │ │ ├── indentation.ts
│ │ │ │ │ ├── lineEdit.ts
│ │ │ │ │ ├── lineRange.ts
│ │ │ │ │ ├── offsetEdit.ts
│ │ │ │ │ ├── offsetRange.ts
│ │ │ │ │ ├── position.ts
│ │ │ │ │ ├── positionToOffset.ts
│ │ │ │ │ ├── range.ts
│ │ │ │ │ ├── rangeMapping.ts
│ │ │ │ │ ├── rgba.ts
│ │ │ │ │ ├── selection.ts
│ │ │ │ │ ├── stringBuilder.ts
│ │ │ │ │ ├── textChange.ts
│ │ │ │ │ ├── textEdit.ts
│ │ │ │ │ ├── textLength.ts
│ │ │ │ │ ├── textModelDefaults.ts
│ │ │ │ │ ├── wordCharacterClassifier.ts
│ │ │ │ │ └── wordHelper.ts
│ │ │ │ ├── cursor/
│ │ │ │ │ ├── cursor.ts
│ │ │ │ │ ├── cursorAtomicMoveOperations.ts
│ │ │ │ │ ├── cursorCollection.ts
│ │ │ │ │ ├── cursorColumnSelection.ts
│ │ │ │ │ ├── cursorContext.ts
│ │ │ │ │ ├── cursorDeleteOperations.ts
│ │ │ │ │ ├── cursorMoveCommands.ts
│ │ │ │ │ ├── cursorMoveOperations.ts
│ │ │ │ │ ├── cursorTypeEditOperations.ts
│ │ │ │ │ ├── cursorTypeOperations.ts
│ │ │ │ │ ├── cursorWordOperations.ts
│ │ │ │ │ └── oneCursor.ts
│ │ │ │ ├── cursorCommon.ts
│ │ │ │ ├── cursorEvents.ts
│ │ │ │ ├── diff/
│ │ │ │ │ ├── defaultLinesDiffComputer/
│ │ │ │ │ │ ├── algorithms/
│ │ │ │ │ │ │ ├── diffAlgorithm.ts
│ │ │ │ │ │ │ ├── dynamicProgrammingDiffing.ts
│ │ │ │ │ │ │ └── myersDiffAlgorithm.ts
│ │ │ │ │ │ ├── computeMovedLines.ts
│ │ │ │ │ │ ├── defaultLinesDiffComputer.ts
│ │ │ │ │ │ ├── heuristicSequenceOptimizations.ts
│ │ │ │ │ │ ├── lineSequence.ts
│ │ │ │ │ │ ├── linesSliceCharSequence.ts
│ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── documentDiffProvider.ts
│ │ │ │ │ ├── legacyLinesDiffComputer.ts
│ │ │ │ │ ├── linesDiffComputer.ts
│ │ │ │ │ ├── linesDiffComputers.ts
│ │ │ │ │ └── rangeMapping.ts
│ │ │ │ ├── editorAction.ts
│ │ │ │ ├── editorCommon.ts
│ │ │ │ ├── editorContextKeys.ts
│ │ │ │ ├── editorFeatures.ts
│ │ │ │ ├── editorTheme.ts
│ │ │ │ ├── encodedTokenAttributes.ts
│ │ │ │ ├── inputMode.ts
│ │ │ │ ├── languageFeatureRegistry.ts
│ │ │ │ ├── languageSelector.ts
│ │ │ │ ├── languages/
│ │ │ │ │ ├── autoIndent.ts
│ │ │ │ │ ├── defaultDocumentColorsComputer.ts
│ │ │ │ │ ├── enterAction.ts
│ │ │ │ │ ├── highlights/
│ │ │ │ │ │ ├── css.scm
│ │ │ │ │ │ ├── ini.scm
│ │ │ │ │ │ ├── regex.scm
│ │ │ │ │ │ └── typescript.scm
│ │ │ │ │ ├── injections/
│ │ │ │ │ │ └── typescript.scm
│ │ │ │ │ ├── language.ts
│ │ │ │ │ ├── languageConfiguration.ts
│ │ │ │ │ ├── languageConfigurationRegistry.ts
│ │ │ │ │ ├── linkComputer.ts
│ │ │ │ │ ├── modesRegistry.ts
│ │ │ │ │ ├── nullTokenize.ts
│ │ │ │ │ ├── supports/
│ │ │ │ │ │ ├── characterPair.ts
│ │ │ │ │ │ ├── electricCharacter.ts
│ │ │ │ │ │ ├── indentRules.ts
│ │ │ │ │ │ ├── indentationLineProcessor.ts
│ │ │ │ │ │ ├── inplaceReplaceSupport.ts
│ │ │ │ │ │ ├── languageBracketsConfiguration.ts
│ │ │ │ │ │ ├── onEnter.ts
│ │ │ │ │ │ ├── richEditBrackets.ts
│ │ │ │ │ │ └── tokenization.ts
│ │ │ │ │ ├── supports.ts
│ │ │ │ │ └── textToHtmlTokenizer.ts
│ │ │ │ ├── languages.ts
│ │ │ │ ├── model/
│ │ │ │ │ ├── bracketPairsTextModelPart/
│ │ │ │ │ │ ├── bracketPairsImpl.ts
│ │ │ │ │ │ ├── bracketPairsTree/
│ │ │ │ │ │ │ ├── ast.ts
│ │ │ │ │ │ │ ├── beforeEditPositionMapper.ts
│ │ │ │ │ │ │ ├── bracketPairsTree.ts
│ │ │ │ │ │ │ ├── brackets.ts
│ │ │ │ │ │ │ ├── combineTextEditInfos.ts
│ │ │ │ │ │ │ ├── concat23Trees.ts
│ │ │ │ │ │ │ ├── length.ts
│ │ │ │ │ │ │ ├── nodeReader.ts
│ │ │ │ │ │ │ ├── parser.ts
│ │ │ │ │ │ │ ├── smallImmutableSet.ts
│ │ │ │ │ │ │ └── tokenizer.ts
│ │ │ │ │ │ ├── colorizedBracketPairsDecorationProvider.ts
│ │ │ │ │ │ └── fixBrackets.ts
│ │ │ │ │ ├── decorationProvider.ts
│ │ │ │ │ ├── editStack.ts
│ │ │ │ │ ├── fixedArray.ts
│ │ │ │ │ ├── guidesTextModelPart.ts
│ │ │ │ │ ├── indentationGuesser.ts
│ │ │ │ │ ├── intervalTree.ts
│ │ │ │ │ ├── mirrorTextModel.ts
│ │ │ │ │ ├── pieceTreeTextBuffer/
│ │ │ │ │ │ ├── pieceTreeBase.ts
│ │ │ │ │ │ ├── pieceTreeTextBuffer.ts
│ │ │ │ │ │ ├── pieceTreeTextBufferBuilder.ts
│ │ │ │ │ │ └── rbTreeBase.ts
│ │ │ │ │ ├── prefixSumComputer.ts
│ │ │ │ │ ├── textModel.ts
│ │ │ │ │ ├── textModelOffsetEdit.ts
│ │ │ │ │ ├── textModelPart.ts
│ │ │ │ │ ├── textModelSearch.ts
│ │ │ │ │ ├── textModelText.ts
│ │ │ │ │ ├── textModelTokens.ts
│ │ │ │ │ ├── tokenStore.ts
│ │ │ │ │ ├── tokenizationTextModelPart.ts
│ │ │ │ │ ├── tokens.ts
│ │ │ │ │ ├── treeSitterTokenStoreService.ts
│ │ │ │ │ ├── treeSitterTokens.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── model.ts
│ │ │ │ ├── modelLineProjectionData.ts
│ │ │ │ ├── services/
│ │ │ │ │ ├── editorBaseApi.ts
│ │ │ │ │ ├── editorWebWorker.ts
│ │ │ │ │ ├── editorWebWorkerMain.ts
│ │ │ │ │ ├── editorWorker.ts
│ │ │ │ │ ├── editorWorkerHost.ts
│ │ │ │ │ ├── findSectionHeaders.ts
│ │ │ │ │ ├── getIconClasses.ts
│ │ │ │ │ ├── languageFeatureDebounce.ts
│ │ │ │ │ ├── languageFeatures.ts
│ │ │ │ │ ├── languageFeaturesService.ts
│ │ │ │ │ ├── languageService.ts
│ │ │ │ │ ├── languagesAssociations.ts
│ │ │ │ │ ├── languagesRegistry.ts
│ │ │ │ │ ├── markerDecorations.ts
│ │ │ │ │ ├── markerDecorationsService.ts
│ │ │ │ │ ├── model.ts
│ │ │ │ │ ├── modelService.ts
│ │ │ │ │ ├── modelUndoRedoParticipant.ts
│ │ │ │ │ ├── resolverService.ts
│ │ │ │ │ ├── semanticTokensDto.ts
│ │ │ │ │ ├── semanticTokensProviderStyling.ts
│ │ │ │ │ ├── semanticTokensStyling.ts
│ │ │ │ │ ├── semanticTokensStylingService.ts
│ │ │ │ │ ├── textModelSync/
│ │ │ │ │ │ ├── textModelSync.impl.ts
│ │ │ │ │ │ └── textModelSync.protocol.ts
│ │ │ │ │ ├── textResourceConfiguration.ts
│ │ │ │ │ ├── textResourceConfigurationService.ts
│ │ │ │ │ ├── treeSitter/
│ │ │ │ │ │ ├── cursorUtils.ts
│ │ │ │ │ │ ├── textModelTreeSitter.ts
│ │ │ │ │ │ ├── treeSitterLanguages.ts
│ │ │ │ │ │ └── treeSitterParserService.ts
│ │ │ │ │ ├── treeSitterParserService.ts
│ │ │ │ │ ├── treeViewsDnd.ts
│ │ │ │ │ ├── treeViewsDndService.ts
│ │ │ │ │ └── unicodeTextModelHighlighter.ts
│ │ │ │ ├── standalone/
│ │ │ │ │ └── standaloneEnums.ts
│ │ │ │ ├── standaloneStrings.ts
│ │ │ │ ├── textModelBracketPairs.ts
│ │ │ │ ├── textModelEvents.ts
│ │ │ │ ├── textModelGuides.ts
│ │ │ │ ├── tokenizationRegistry.ts
│ │ │ │ ├── tokenizationTextModelPart.ts
│ │ │ │ ├── tokens/
│ │ │ │ │ ├── contiguousMultilineTokens.ts
│ │ │ │ │ ├── contiguousMultilineTokensBuilder.ts
│ │ │ │ │ ├── contiguousTokensEditing.ts
│ │ │ │ │ ├── contiguousTokensStore.ts
│ │ │ │ │ ├── lineTokens.ts
│ │ │ │ │ ├── sparseMultilineTokens.ts
│ │ │ │ │ ├── sparseTokensStore.ts
│ │ │ │ │ └── tokenArray.ts
│ │ │ │ ├── viewEventHandler.ts
│ │ │ │ ├── viewEvents.ts
│ │ │ │ ├── viewLayout/
│ │ │ │ │ ├── lineDecorations.ts
│ │ │ │ │ ├── linePart.ts
│ │ │ │ │ ├── linesLayout.ts
│ │ │ │ │ ├── viewLayout.ts
│ │ │ │ │ ├── viewLineRenderer.ts
│ │ │ │ │ └── viewLinesViewportData.ts
│ │ │ │ ├── viewModel/
│ │ │ │ │ ├── glyphLanesModel.ts
│ │ │ │ │ ├── minimapTokensColorTracker.ts
│ │ │ │ │ ├── modelLineProjection.ts
│ │ │ │ │ ├── monospaceLineBreaksComputer.ts
│ │ │ │ │ ├── overviewZoneManager.ts
│ │ │ │ │ ├── viewContext.ts
│ │ │ │ │ ├── viewModelDecorations.ts
│ │ │ │ │ ├── viewModelImpl.ts
│ │ │ │ │ └── viewModelLines.ts
│ │ │ │ ├── viewModel.ts
│ │ │ │ └── viewModelEventDispatcher.ts
│ │ │ ├── contrib/
│ │ │ │ ├── anchorSelect/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── anchorSelect.css
│ │ │ │ │ └── anchorSelect.ts
│ │ │ │ ├── bracketMatching/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── bracketMatching.css
│ │ │ │ │ │ └── bracketMatching.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── bracketMatching.test.ts
│ │ │ │ ├── caretOperations/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── caretOperations.ts
│ │ │ │ │ │ ├── moveCaretCommand.ts
│ │ │ │ │ │ └── transpose.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── moveCarretCommand.test.ts
│ │ │ │ ├── clipboard/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── clipboard.ts
│ │ │ │ ├── codeAction/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── codeAction.ts
│ │ │ │ │ │ ├── codeActionCommands.ts
│ │ │ │ │ │ ├── codeActionContributions.ts
│ │ │ │ │ │ ├── codeActionController.ts
│ │ │ │ │ │ ├── codeActionKeybindingResolver.ts
│ │ │ │ │ │ ├── codeActionMenu.ts
│ │ │ │ │ │ ├── codeActionModel.ts
│ │ │ │ │ │ ├── lightBulbWidget.css
│ │ │ │ │ │ └── lightBulbWidget.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── codeAction.test.ts
│ │ │ │ │ ├── codeActionKeybindingResolver.test.ts
│ │ │ │ │ └── codeActionModel.test.ts
│ │ │ │ ├── codelens/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── codeLensCache.ts
│ │ │ │ │ ├── codelens.ts
│ │ │ │ │ ├── codelensController.ts
│ │ │ │ │ ├── codelensWidget.css
│ │ │ │ │ └── codelensWidget.ts
│ │ │ │ ├── colorPicker/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── color.ts
│ │ │ │ │ ├── colorDetector.ts
│ │ │ │ │ ├── colorPicker.css
│ │ │ │ │ ├── colorPickerContribution.ts
│ │ │ │ │ ├── colorPickerModel.ts
│ │ │ │ │ ├── colorPickerParticipantUtils.ts
│ │ │ │ │ ├── colorPickerParts/
│ │ │ │ │ │ ├── colorPickerBody.ts
│ │ │ │ │ │ ├── colorPickerCloseButton.ts
│ │ │ │ │ │ ├── colorPickerHeader.ts
│ │ │ │ │ │ ├── colorPickerInsertButton.ts
│ │ │ │ │ │ ├── colorPickerSaturationBox.ts
│ │ │ │ │ │ └── colorPickerStrip.ts
│ │ │ │ │ ├── colorPickerWidget.ts
│ │ │ │ │ ├── defaultDocumentColorProvider.ts
│ │ │ │ │ ├── hoverColorPicker/
│ │ │ │ │ │ ├── hoverColorPicker.ts
│ │ │ │ │ │ ├── hoverColorPickerContribution.ts
│ │ │ │ │ │ └── hoverColorPickerParticipant.ts
│ │ │ │ │ └── standaloneColorPicker/
│ │ │ │ │ ├── standaloneColorPickerActions.ts
│ │ │ │ │ ├── standaloneColorPickerController.ts
│ │ │ │ │ ├── standaloneColorPickerParticipant.ts
│ │ │ │ │ └── standaloneColorPickerWidget.ts
│ │ │ │ ├── comment/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── blockCommentCommand.ts
│ │ │ │ │ │ ├── comment.ts
│ │ │ │ │ │ └── lineCommentCommand.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── blockCommentCommand.test.ts
│ │ │ │ │ └── lineCommentCommand.test.ts
│ │ │ │ ├── contextmenu/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── contextmenu.ts
│ │ │ │ ├── cursorUndo/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── cursorUndo.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── cursorUndo.test.ts
│ │ │ │ ├── diffEditorBreadcrumbs/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── contribution.ts
│ │ │ │ ├── dnd/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── dnd.css
│ │ │ │ │ ├── dnd.ts
│ │ │ │ │ └── dragAndDropCommand.ts
│ │ │ │ ├── documentSymbols/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── documentSymbols.ts
│ │ │ │ │ │ └── outlineModel.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── outlineModel.test.ts
│ │ │ │ ├── dropOrPasteInto/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── copyPasteContribution.ts
│ │ │ │ │ │ ├── copyPasteController.ts
│ │ │ │ │ │ ├── defaultProviders.ts
│ │ │ │ │ │ ├── dropIntoEditorContribution.ts
│ │ │ │ │ │ ├── dropIntoEditorController.ts
│ │ │ │ │ │ ├── edit.ts
│ │ │ │ │ │ ├── postEditWidget.css
│ │ │ │ │ │ └── postEditWidget.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── editSort.test.ts
│ │ │ │ ├── editorState/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── editorState.ts
│ │ │ │ │ │ └── keybindingCancellation.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── editorState.test.ts
│ │ │ │ ├── find/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── findController.ts
│ │ │ │ │ │ ├── findDecorations.ts
│ │ │ │ │ │ ├── findModel.ts
│ │ │ │ │ │ ├── findOptionsWidget.css
│ │ │ │ │ │ ├── findOptionsWidget.ts
│ │ │ │ │ │ ├── findState.ts
│ │ │ │ │ │ ├── findWidget.css
│ │ │ │ │ │ ├── findWidget.ts
│ │ │ │ │ │ ├── findWidgetSearchHistory.ts
│ │ │ │ │ │ ├── replaceAllCommand.ts
│ │ │ │ │ │ ├── replacePattern.ts
│ │ │ │ │ │ └── replaceWidgetHistory.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── find.test.ts
│ │ │ │ │ ├── findController.test.ts
│ │ │ │ │ ├── findModel.test.ts
│ │ │ │ │ └── replacePattern.test.ts
│ │ │ │ ├── folding/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── folding.css
│ │ │ │ │ │ ├── folding.ts
│ │ │ │ │ │ ├── foldingDecorations.ts
│ │ │ │ │ │ ├── foldingModel.ts
│ │ │ │ │ │ ├── foldingRanges.ts
│ │ │ │ │ │ ├── hiddenRangeModel.ts
│ │ │ │ │ │ ├── indentRangeProvider.ts
│ │ │ │ │ │ └── syntaxRangeProvider.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── foldingModel.test.ts
│ │ │ │ │ ├── foldingRanges.test.ts
│ │ │ │ │ ├── hiddenRangeModel.test.ts
│ │ │ │ │ ├── indentFold.test.ts
│ │ │ │ │ ├── indentRangeProvider.test.ts
│ │ │ │ │ └── syntaxFold.test.ts
│ │ │ │ ├── fontZoom/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── fontZoom.ts
│ │ │ │ ├── format/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── format.ts
│ │ │ │ │ ├── formatActions.ts
│ │ │ │ │ └── formattingEdit.ts
│ │ │ │ ├── gotoError/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── gotoError.ts
│ │ │ │ │ ├── gotoErrorWidget.ts
│ │ │ │ │ ├── markerNavigationService.ts
│ │ │ │ │ └── media/
│ │ │ │ │ └── gotoErrorWidget.css
│ │ │ │ ├── gotoSymbol/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── goToCommands.ts
│ │ │ │ │ │ ├── goToSymbol.ts
│ │ │ │ │ │ ├── link/
│ │ │ │ │ │ │ ├── clickLinkGesture.ts
│ │ │ │ │ │ │ ├── goToDefinitionAtPosition.css
│ │ │ │ │ │ │ └── goToDefinitionAtPosition.ts
│ │ │ │ │ │ ├── peek/
│ │ │ │ │ │ │ ├── referencesController.ts
│ │ │ │ │ │ │ ├── referencesTree.ts
│ │ │ │ │ │ │ ├── referencesWidget.css
│ │ │ │ │ │ │ └── referencesWidget.ts
│ │ │ │ │ │ ├── referencesModel.ts
│ │ │ │ │ │ └── symbolNavigation.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── referencesModel.test.ts
│ │ │ │ ├── gpu/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── gpuActions.ts
│ │ │ │ ├── hover/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── contentHoverComputer.ts
│ │ │ │ │ │ ├── contentHoverController.ts
│ │ │ │ │ │ ├── contentHoverRendered.ts
│ │ │ │ │ │ ├── contentHoverStatusBar.ts
│ │ │ │ │ │ ├── contentHoverTypes.ts
│ │ │ │ │ │ ├── contentHoverWidget.ts
│ │ │ │ │ │ ├── contentHoverWidgetWrapper.ts
│ │ │ │ │ │ ├── getHover.ts
│ │ │ │ │ │ ├── glyphHoverComputer.ts
│ │ │ │ │ │ ├── glyphHoverController.ts
│ │ │ │ │ │ ├── glyphHoverWidget.ts
│ │ │ │ │ │ ├── hover.css
│ │ │ │ │ │ ├── hoverAccessibleViews.ts
│ │ │ │ │ │ ├── hoverActionIds.ts
│ │ │ │ │ │ ├── hoverActions.ts
│ │ │ │ │ │ ├── hoverContribution.ts
│ │ │ │ │ │ ├── hoverOperation.ts
│ │ │ │ │ │ ├── hoverTypes.ts
│ │ │ │ │ │ ├── hoverUtils.ts
│ │ │ │ │ │ ├── markdownHoverParticipant.ts
│ │ │ │ │ │ ├── markerHoverParticipant.ts
│ │ │ │ │ │ └── resizableContentWidget.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── contentHover.test.ts
│ │ │ │ ├── inPlaceReplace/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── inPlaceReplace.css
│ │ │ │ │ ├── inPlaceReplace.ts
│ │ │ │ │ └── inPlaceReplaceCommand.ts
│ │ │ │ ├── indentation/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── indentation.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── indentUtils.ts
│ │ │ │ │ │ └── indentation.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── indentation.test.ts
│ │ │ │ │ └── indentationLineProcessor.test.ts
│ │ │ │ ├── inlayHints/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── inlayHints.ts
│ │ │ │ │ ├── inlayHintsContribution.ts
│ │ │ │ │ ├── inlayHintsController.ts
│ │ │ │ │ ├── inlayHintsHover.ts
│ │ │ │ │ └── inlayHintsLocations.ts
│ │ │ │ ├── inlineCompletions/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── controller/
│ │ │ │ │ │ │ ├── commandIds.ts
│ │ │ │ │ │ │ ├── commands.ts
│ │ │ │ │ │ │ ├── inlineCompletionContextKeys.ts
│ │ │ │ │ │ │ └── inlineCompletionsController.ts
│ │ │ │ │ │ ├── hintsWidget/
│ │ │ │ │ │ │ ├── hoverParticipant.ts
│ │ │ │ │ │ │ ├── inlineCompletionsHintsWidget.css
│ │ │ │ │ │ │ └── inlineCompletionsHintsWidget.ts
│ │ │ │ │ │ ├── inlineCompletions.contribution.ts
│ │ │ │ │ │ ├── inlineCompletionsAccessibleView.ts
│ │ │ │ │ │ ├── model/
│ │ │ │ │ │ │ ├── animation.ts
│ │ │ │ │ │ │ ├── changeRecorder.ts
│ │ │ │ │ │ │ ├── computeGhostText.ts
│ │ │ │ │ │ │ ├── ghostText.ts
│ │ │ │ │ │ │ ├── inlineCompletionsModel.ts
│ │ │ │ │ │ │ ├── inlineCompletionsSource.ts
│ │ │ │ │ │ │ ├── inlineEdit.ts
│ │ │ │ │ │ │ ├── inlineEditsAdapter.ts
│ │ │ │ │ │ │ ├── provideInlineCompletions.ts
│ │ │ │ │ │ │ ├── singleTextEditHelpers.ts
│ │ │ │ │ │ │ └── suggestWidgetAdapter.ts
│ │ │ │ │ │ ├── structuredLogger.ts
│ │ │ │ │ │ ├── utils.ts
│ │ │ │ │ │ └── view/
│ │ │ │ │ │ ├── ghostText/
│ │ │ │ │ │ │ ├── ghostTextView.css
│ │ │ │ │ │ │ └── ghostTextView.ts
│ │ │ │ │ │ ├── inlineCompletionsView.ts
│ │ │ │ │ │ └── inlineEdits/
│ │ │ │ │ │ ├── components/
│ │ │ │ │ │ │ ├── gutterIndicatorMenu.ts
│ │ │ │ │ │ │ ├── gutterIndicatorView.ts
│ │ │ │ │ │ │ └── indicatorView.ts
│ │ │ │ │ │ ├── inlineEditWithChanges.ts
│ │ │ │ │ │ ├── inlineEditsModel.ts
│ │ │ │ │ │ ├── inlineEditsView.ts
│ │ │ │ │ │ ├── inlineEditsViewInterface.ts
│ │ │ │ │ │ ├── inlineEditsViewProducer.ts
│ │ │ │ │ │ ├── inlineEditsViews/
│ │ │ │ │ │ │ ├── debugVisualization.ts
│ │ │ │ │ │ │ ├── inlineEditsCollapsedView.ts
│ │ │ │ │ │ │ ├── inlineEditsDeletionView.ts
│ │ │ │ │ │ │ ├── inlineEditsInsertionView.ts
│ │ │ │ │ │ │ ├── inlineEditsLineReplacementView.ts
│ │ │ │ │ │ │ ├── inlineEditsSideBySideView.ts
│ │ │ │ │ │ │ ├── inlineEditsWordInsertView.ts
│ │ │ │ │ │ │ ├── inlineEditsWordReplacementView.ts
│ │ │ │ │ │ │ └── originalEditorInlineDiffView.ts
│ │ │ │ │ │ ├── theme.ts
│ │ │ │ │ │ ├── utils/
│ │ │ │ │ │ │ └── utils.ts
│ │ │ │ │ │ └── view.css
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── inlineCompletionsModel.test.ts
│ │ │ │ │ ├── inlineCompletionsProvider.test.ts
│ │ │ │ │ ├── suggestWidgetModel.test.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── inlineProgress/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── inlineProgress.ts
│ │ │ │ │ └── inlineProgressWidget.css
│ │ │ │ ├── insertFinalNewLine/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── insertFinalNewLine.ts
│ │ │ │ │ └── insertFinalNewLineCommand.ts
│ │ │ │ ├── lineSelection/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── lineSelection.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── lineSelection.test.ts
│ │ │ │ ├── linesOperations/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── copyLinesCommand.ts
│ │ │ │ │ │ ├── linesOperations.ts
│ │ │ │ │ │ ├── moveLinesCommand.ts
│ │ │ │ │ │ └── sortLinesCommand.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── copyLinesCommand.test.ts
│ │ │ │ │ ├── linesOperations.test.ts
│ │ │ │ │ ├── moveLinesCommand.test.ts
│ │ │ │ │ └── sortLinesCommand.test.ts
│ │ │ │ ├── linkedEditing/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── linkedEditing.css
│ │ │ │ │ │ └── linkedEditing.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── linkedEditing.test.ts
│ │ │ │ ├── links/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── getLinks.ts
│ │ │ │ │ ├── links.css
│ │ │ │ │ └── links.ts
│ │ │ │ ├── longLinesHelper/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── longLinesHelper.ts
│ │ │ │ ├── message/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── messageController.css
│ │ │ │ │ └── messageController.ts
│ │ │ │ ├── multicursor/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── multicursor.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── multicursor.test.ts
│ │ │ │ ├── parameterHints/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── parameterHints.css
│ │ │ │ │ │ ├── parameterHints.ts
│ │ │ │ │ │ ├── parameterHintsModel.ts
│ │ │ │ │ │ ├── parameterHintsWidget.ts
│ │ │ │ │ │ └── provideSignatureHelp.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── parameterHintsModel.test.ts
│ │ │ │ ├── peekView/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── peekViewWidget.css
│ │ │ │ │ └── peekView.ts
│ │ │ │ ├── placeholderText/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── placeholderText.contribution.ts
│ │ │ │ │ ├── placeholderText.css
│ │ │ │ │ └── placeholderTextContribution.ts
│ │ │ │ ├── quickAccess/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── commandsQuickAccess.ts
│ │ │ │ │ ├── editorNavigationQuickAccess.ts
│ │ │ │ │ ├── gotoLineQuickAccess.ts
│ │ │ │ │ └── gotoSymbolQuickAccess.ts
│ │ │ │ ├── readOnlyMessage/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── contribution.ts
│ │ │ │ ├── rename/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── rename.ts
│ │ │ │ │ ├── renameWidget.css
│ │ │ │ │ └── renameWidget.ts
│ │ │ │ ├── sectionHeaders/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── sectionHeaders.ts
│ │ │ │ ├── semanticTokens/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── documentSemanticTokens.ts
│ │ │ │ │ │ └── viewportSemanticTokens.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── getSemanticTokens.ts
│ │ │ │ │ │ └── semanticTokensConfig.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── documentSemanticTokens.test.ts
│ │ │ │ │ └── getSemanticTokens.test.ts
│ │ │ │ ├── smartSelect/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── bracketSelections.ts
│ │ │ │ │ │ ├── smartSelect.ts
│ │ │ │ │ │ └── wordSelections.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── smartSelect.test.ts
│ │ │ │ ├── snippet/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── snippet.md
│ │ │ │ │ │ ├── snippetController2.ts
│ │ │ │ │ │ ├── snippetParser.ts
│ │ │ │ │ │ ├── snippetSession.css
│ │ │ │ │ │ ├── snippetSession.ts
│ │ │ │ │ │ └── snippetVariables.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── snippetController2.old.test.ts
│ │ │ │ │ ├── snippetController2.test.ts
│ │ │ │ │ ├── snippetParser.test.ts
│ │ │ │ │ ├── snippetSession.test.ts
│ │ │ │ │ └── snippetVariables.test.ts
│ │ │ │ ├── stickyScroll/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── stickyScroll.css
│ │ │ │ │ │ ├── stickyScrollActions.ts
│ │ │ │ │ │ ├── stickyScrollContribution.ts
│ │ │ │ │ │ ├── stickyScrollController.ts
│ │ │ │ │ │ ├── stickyScrollElement.ts
│ │ │ │ │ │ ├── stickyScrollModelProvider.ts
│ │ │ │ │ │ ├── stickyScrollProvider.ts
│ │ │ │ │ │ └── stickyScrollWidget.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── stickyScroll.test.ts
│ │ │ │ ├── suggest/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── completionModel.ts
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── suggest.css
│ │ │ │ │ │ ├── suggest.ts
│ │ │ │ │ │ ├── suggestAlternatives.ts
│ │ │ │ │ │ ├── suggestCommitCharacters.ts
│ │ │ │ │ │ ├── suggestController.ts
│ │ │ │ │ │ ├── suggestInlineCompletions.ts
│ │ │ │ │ │ ├── suggestMemory.ts
│ │ │ │ │ │ ├── suggestModel.ts
│ │ │ │ │ │ ├── suggestOvertypingCapturer.ts
│ │ │ │ │ │ ├── suggestWidget.ts
│ │ │ │ │ │ ├── suggestWidgetDetails.ts
│ │ │ │ │ │ ├── suggestWidgetRenderer.ts
│ │ │ │ │ │ ├── suggestWidgetStatus.ts
│ │ │ │ │ │ ├── wordContextKey.ts
│ │ │ │ │ │ └── wordDistance.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── completionModel.test.ts
│ │ │ │ │ ├── suggest.test.ts
│ │ │ │ │ ├── suggestController.test.ts
│ │ │ │ │ ├── suggestInlineCompletions.test.ts
│ │ │ │ │ ├── suggestMemory.test.ts
│ │ │ │ │ ├── suggestModel.test.ts
│ │ │ │ │ └── wordDistance.test.ts
│ │ │ │ ├── symbolIcons/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── symbolIcons.css
│ │ │ │ │ └── symbolIcons.ts
│ │ │ │ ├── toggleTabFocusMode/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── toggleTabFocusMode.ts
│ │ │ │ ├── tokenization/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── tokenization.ts
│ │ │ │ ├── unicodeHighlighter/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── bannerController.css
│ │ │ │ │ ├── bannerController.ts
│ │ │ │ │ ├── unicodeHighlighter.css
│ │ │ │ │ └── unicodeHighlighter.ts
│ │ │ │ ├── unusualLineTerminators/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── unusualLineTerminators.ts
│ │ │ │ ├── wordHighlighter/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── highlightDecorations.css
│ │ │ │ │ ├── highlightDecorations.ts
│ │ │ │ │ ├── textualHighlightProvider.ts
│ │ │ │ │ └── wordHighlighter.ts
│ │ │ │ ├── wordOperations/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── wordOperations.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── wordOperations.test.ts
│ │ │ │ │ └── wordTestUtils.ts
│ │ │ │ ├── wordPartOperations/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── wordPartOperations.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── utils.ts
│ │ │ │ │ └── wordPartOperations.test.ts
│ │ │ │ └── zoneWidget/
│ │ │ │ └── browser/
│ │ │ │ ├── zoneWidget.css
│ │ │ │ └── zoneWidget.ts
│ │ │ ├── editor.all.ts
│ │ │ ├── editor.api.ts
│ │ │ ├── editor.main.ts
│ │ │ ├── editor.worker.start.ts
│ │ │ ├── standalone/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── colorizer.ts
│ │ │ │ │ ├── iPadShowKeyboard/
│ │ │ │ │ │ ├── iPadShowKeyboard.css
│ │ │ │ │ │ └── iPadShowKeyboard.ts
│ │ │ │ │ ├── inspectTokens/
│ │ │ │ │ │ ├── inspectTokens.css
│ │ │ │ │ │ └── inspectTokens.ts
│ │ │ │ │ ├── quickAccess/
│ │ │ │ │ │ ├── standaloneCommandsQuickAccess.ts
│ │ │ │ │ │ ├── standaloneGotoLineQuickAccess.ts
│ │ │ │ │ │ ├── standaloneGotoSymbolQuickAccess.ts
│ │ │ │ │ │ └── standaloneHelpQuickAccess.ts
│ │ │ │ │ ├── quickInput/
│ │ │ │ │ │ ├── standaloneQuickInput.css
│ │ │ │ │ │ └── standaloneQuickInputService.ts
│ │ │ │ │ ├── referenceSearch/
│ │ │ │ │ │ └── standaloneReferenceSearch.ts
│ │ │ │ │ ├── standalone-tokens.css
│ │ │ │ │ ├── standaloneCodeEditor.ts
│ │ │ │ │ ├── standaloneCodeEditorService.ts
│ │ │ │ │ ├── standaloneEditor.ts
│ │ │ │ │ ├── standaloneLanguages.ts
│ │ │ │ │ ├── standaloneLayoutService.ts
│ │ │ │ │ ├── standaloneServices.ts
│ │ │ │ │ ├── standaloneThemeService.ts
│ │ │ │ │ ├── standaloneTreeSitterService.ts
│ │ │ │ │ ├── standaloneWebWorker.ts
│ │ │ │ │ └── toggleHighContrast/
│ │ │ │ │ └── toggleHighContrast.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── monarch/
│ │ │ │ │ │ ├── monarchCommon.ts
│ │ │ │ │ │ ├── monarchCompile.ts
│ │ │ │ │ │ ├── monarchLexer.ts
│ │ │ │ │ │ └── monarchTypes.ts
│ │ │ │ │ ├── standaloneTheme.ts
│ │ │ │ │ └── themes.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── monarch.test.ts
│ │ │ │ ├── standaloneLanguages.test.ts
│ │ │ │ └── standaloneServices.test.ts
│ │ │ └── test/
│ │ │ ├── browser/
│ │ │ │ ├── commands/
│ │ │ │ │ ├── shiftCommand.test.ts
│ │ │ │ │ ├── sideEditing.test.ts
│ │ │ │ │ └── trimTrailingWhitespaceCommand.test.ts
│ │ │ │ ├── config/
│ │ │ │ │ ├── editorConfiguration.test.ts
│ │ │ │ │ ├── editorLayoutProvider.test.ts
│ │ │ │ │ └── testConfiguration.ts
│ │ │ │ ├── controller/
│ │ │ │ │ ├── cursor.integrationTest.ts
│ │ │ │ │ ├── cursor.test.ts
│ │ │ │ │ ├── cursorMoveCommand.test.ts
│ │ │ │ │ ├── imeRecordedTypes.ts
│ │ │ │ │ ├── imeRecorder.html
│ │ │ │ │ ├── imeRecorder.ts
│ │ │ │ │ ├── imeTester.html
│ │ │ │ │ ├── imeTester.ts
│ │ │ │ │ ├── textAreaInput.test.ts
│ │ │ │ │ └── textAreaState.test.ts
│ │ │ │ ├── diff/
│ │ │ │ │ └── testDiffProviderFactoryService.ts
│ │ │ │ ├── editorTestServices.ts
│ │ │ │ ├── gpu/
│ │ │ │ │ ├── atlas/
│ │ │ │ │ │ ├── testUtil.ts
│ │ │ │ │ │ ├── textureAtlas.test.ts
│ │ │ │ │ │ └── textureAtlasAllocator.test.ts
│ │ │ │ │ ├── bufferDirtyTracker.test.ts
│ │ │ │ │ ├── decorationCssRulerExtractor.test.ts
│ │ │ │ │ └── objectCollectionBuffer.test.ts
│ │ │ │ ├── services/
│ │ │ │ │ ├── decorationRenderOptions.test.ts
│ │ │ │ │ ├── openerService.test.ts
│ │ │ │ │ └── treeSitterParserService.test.ts
│ │ │ │ ├── testCodeEditor.ts
│ │ │ │ ├── testCommand.ts
│ │ │ │ ├── view/
│ │ │ │ │ ├── minimapCharRenderer.test.ts
│ │ │ │ │ └── viewLayer.test.ts
│ │ │ │ ├── viewModel/
│ │ │ │ │ ├── modelLineProjection.test.ts
│ │ │ │ │ ├── testViewModel.ts
│ │ │ │ │ ├── viewModelDecorations.test.ts
│ │ │ │ │ └── viewModelImpl.test.ts
│ │ │ │ └── widget/
│ │ │ │ ├── codeEditorWidget.test.ts
│ │ │ │ ├── diffEditorWidget.test.ts
│ │ │ │ └── observableCodeEditor.test.ts
│ │ │ ├── common/
│ │ │ │ ├── codecs/
│ │ │ │ │ ├── linesDecoder.test.ts
│ │ │ │ │ ├── markdownDecoder.test.ts
│ │ │ │ │ └── simpleDecoder.test.ts
│ │ │ │ ├── controller/
│ │ │ │ │ └── cursorAtomicMoveOperations.test.ts
│ │ │ │ ├── core/
│ │ │ │ │ ├── characterClassifier.test.ts
│ │ │ │ │ ├── cursorColumns.test.ts
│ │ │ │ │ ├── lineRange.test.ts
│ │ │ │ │ ├── lineTokens.test.ts
│ │ │ │ │ ├── positionOffsetTransformer.test.ts
│ │ │ │ │ ├── random.ts
│ │ │ │ │ ├── range.test.ts
│ │ │ │ │ ├── stringBuilder.test.ts
│ │ │ │ │ ├── testLineToken.ts
│ │ │ │ │ └── textEdit.test.ts
│ │ │ │ ├── diff/
│ │ │ │ │ └── diffComputer.test.ts
│ │ │ │ ├── model/
│ │ │ │ │ ├── bracketPairColorizer/
│ │ │ │ │ │ ├── beforeEditPositionMapper.test.ts
│ │ │ │ │ │ ├── brackets.test.ts
│ │ │ │ │ │ ├── combineTextEditInfos.test.ts
│ │ │ │ │ │ ├── concat23Trees.test.ts
│ │ │ │ │ │ ├── getBracketPairsInRange.test.ts
│ │ │ │ │ │ ├── length.test.ts
│ │ │ │ │ │ ├── smallImmutableSet.test.ts
│ │ │ │ │ │ └── tokenizer.test.ts
│ │ │ │ │ ├── editStack.test.ts
│ │ │ │ │ ├── editableTextModel.test.ts
│ │ │ │ │ ├── editableTextModelAuto.test.ts
│ │ │ │ │ ├── editableTextModelTestUtils.ts
│ │ │ │ │ ├── intervalTree.test.ts
│ │ │ │ │ ├── linesTextBuffer/
│ │ │ │ │ │ ├── linesTextBuffer.test.ts
│ │ │ │ │ │ └── linesTextBufferBuilder.test.ts
│ │ │ │ │ ├── model.line.test.ts
│ │ │ │ │ ├── model.modes.test.ts
│ │ │ │ │ ├── model.test.ts
│ │ │ │ │ ├── modelDecorations.test.ts
│ │ │ │ │ ├── modelEditOperation.test.ts
│ │ │ │ │ ├── modelInjectedText.test.ts
│ │ │ │ │ ├── pieceTreeTextBuffer/
│ │ │ │ │ │ └── pieceTreeTextBuffer.test.ts
│ │ │ │ │ ├── textChange.test.ts
│ │ │ │ │ ├── textModel.test.ts
│ │ │ │ │ ├── textModelSearch.test.ts
│ │ │ │ │ ├── textModelTokens.test.ts
│ │ │ │ │ ├── textModelWithTokens.test.ts
│ │ │ │ │ ├── tokenStore.test.ts
│ │ │ │ │ └── tokensStore.test.ts
│ │ │ │ ├── modes/
│ │ │ │ │ ├── languageConfiguration.test.ts
│ │ │ │ │ ├── languageSelector.test.ts
│ │ │ │ │ ├── linkComputer.test.ts
│ │ │ │ │ ├── supports/
│ │ │ │ │ │ ├── autoClosingPairsRules.ts
│ │ │ │ │ │ ├── bracketRules.ts
│ │ │ │ │ │ ├── characterPair.test.ts
│ │ │ │ │ │ ├── electricCharacter.test.ts
│ │ │ │ │ │ ├── indentationRules.ts
│ │ │ │ │ │ ├── onEnter.test.ts
│ │ │ │ │ │ ├── onEnterRules.ts
│ │ │ │ │ │ ├── richEditBrackets.test.ts
│ │ │ │ │ │ └── tokenization.test.ts
│ │ │ │ │ ├── testLanguageConfigurationService.ts
│ │ │ │ │ └── textToHtmlTokenizer.test.ts
│ │ │ │ ├── modesTestUtils.ts
│ │ │ │ ├── services/
│ │ │ │ │ ├── editorWebWorker.test.ts
│ │ │ │ │ ├── findSectionHeaders.test.ts
│ │ │ │ │ ├── languageService.test.ts
│ │ │ │ │ ├── languagesAssociations.test.ts
│ │ │ │ │ ├── languagesRegistry.test.ts
│ │ │ │ │ ├── modelService.test.ts
│ │ │ │ │ ├── semanticTokensDto.test.ts
│ │ │ │ │ ├── semanticTokensProviderStyling.test.ts
│ │ │ │ │ ├── testEditorWorkerService.ts
│ │ │ │ │ ├── testTextResourcePropertiesService.ts
│ │ │ │ │ ├── testTreeSitterService.ts
│ │ │ │ │ ├── textResourceConfigurationService.test.ts
│ │ │ │ │ └── unicodeTextModelHighlighter.test.ts
│ │ │ │ ├── testTextModel.ts
│ │ │ │ ├── utils/
│ │ │ │ │ └── testDecoder.ts
│ │ │ │ ├── view/
│ │ │ │ │ └── overviewZoneManager.test.ts
│ │ │ │ ├── viewLayout/
│ │ │ │ │ ├── lineDecorations.test.ts
│ │ │ │ │ ├── linesLayout.test.ts
│ │ │ │ │ └── viewLineRenderer.test.ts
│ │ │ │ └── viewModel/
│ │ │ │ ├── glyphLanesModel.test.ts
│ │ │ │ ├── lineBreakData.test.ts
│ │ │ │ ├── monospaceLineBreaksComputer.test.ts
│ │ │ │ └── prefixSumComputer.test.ts
│ │ │ └── node/
│ │ │ └── diffing/
│ │ │ ├── README.md
│ │ │ ├── defaultLinesDiffComputer.test.ts
│ │ │ ├── fixtures/
│ │ │ │ ├── bracket-aligning/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── class-replacement/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ ├── advanced.human.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── deletion/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── difficult-move/
│ │ │ │ │ ├── 1.js
│ │ │ │ │ ├── 2.js
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── equals/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── false-positive-move/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── fuzzy-matching/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── import-shifting/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── indentation/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── intra-block-align/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── invalid-diff-bug/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── invalid-diff-trimws/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── invalid-ranges/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── issue-131091/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── issue-185779/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── issue-201713/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── issue-202147-trimws/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── issue-204948/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── issue-214049/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── json-brackets/
│ │ │ │ │ ├── 1.json
│ │ │ │ │ ├── 2.json
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── just-whitespace/
│ │ │ │ │ ├── 1.js
│ │ │ │ │ ├── 2.js
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── method-splitting/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── minimal-diff-character/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── move-1/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── noise-1/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── noise-2/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── noisy-move1/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── penalize-fragmentation/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ ├── advanced.human.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── random-match-1/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── random-match-2/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── random-match-3/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── shifting-parameters/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── shifting-twice/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── sorted-offsets/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── subword/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── trivial/
│ │ │ │ │ ├── 1.txt
│ │ │ │ │ ├── 2.txt
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-advanced-bug/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-class/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ ├── advanced.human.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-comments/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-confusing/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-confusing-2/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-diff-word-split/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-example1/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-example2-ts/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-fragmented-eager-diffing/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-fragmented-eager-diffing2/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-fragmented-eager-diffing3/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-import-ws-affinity/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-insert/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-methods/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-shift-to-ws/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-shifting/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-strings/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-too-much-minimization/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-unfragmented-diffing/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── ts-unit-test/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ ├── word-shared-letters/
│ │ │ │ │ ├── 1.tst
│ │ │ │ │ ├── 2.tst
│ │ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ │ └── legacy.expected.diff.json
│ │ │ │ └── ws-alignment/
│ │ │ │ ├── 1.tsx
│ │ │ │ ├── 2.tsx
│ │ │ │ ├── advanced.expected.diff.json
│ │ │ │ └── legacy.expected.diff.json
│ │ │ └── fixtures.test.ts
│ │ ├── loader.js
│ │ ├── monaco.d.ts
│ │ ├── nls.messages.ts
│ │ ├── nls.ts
│ │ ├── platform/
│ │ │ ├── accessibility/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── accessibilityService.ts
│ │ │ │ │ ├── accessibleView.ts
│ │ │ │ │ └── accessibleViewRegistry.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── accessibility.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── testAccessibilityService.ts
│ │ │ ├── accessibilitySignal/
│ │ │ │ └── browser/
│ │ │ │ ├── accessibilitySignalService.ts
│ │ │ │ └── progressAccessibilitySignalScheduler.ts
│ │ │ ├── action/
│ │ │ │ └── common/
│ │ │ │ ├── action.ts
│ │ │ │ └── actionCommonCategories.ts
│ │ │ ├── actionWidget/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── actionList.ts
│ │ │ │ │ ├── actionWidget.css
│ │ │ │ │ └── actionWidget.ts
│ │ │ │ └── common/
│ │ │ │ └── actionWidget.ts
│ │ │ ├── actions/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── actionViewItemService.ts
│ │ │ │ │ ├── buttonbar.ts
│ │ │ │ │ ├── dropdownActionViewItemWithKeybinding.ts
│ │ │ │ │ ├── dropdownWithPrimaryActionViewItem.ts
│ │ │ │ │ ├── floatingMenu.ts
│ │ │ │ │ ├── menuEntryActionViewItem.css
│ │ │ │ │ ├── menuEntryActionViewItem.ts
│ │ │ │ │ └── toolbar.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── actions.contribution.ts
│ │ │ │ │ ├── actions.ts
│ │ │ │ │ ├── menuResetAction.ts
│ │ │ │ │ └── menuService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── menuService.test.ts
│ │ │ ├── assignment/
│ │ │ │ └── common/
│ │ │ │ ├── assignment.ts
│ │ │ │ └── assignmentService.ts
│ │ │ ├── auxiliaryWindow/
│ │ │ │ └── electron-main/
│ │ │ │ ├── auxiliaryWindow.ts
│ │ │ │ ├── auxiliaryWindows.ts
│ │ │ │ └── auxiliaryWindowsMainService.ts
│ │ │ ├── backup/
│ │ │ │ ├── common/
│ │ │ │ │ └── backup.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── backup.ts
│ │ │ │ │ └── backupMainService.ts
│ │ │ │ ├── node/
│ │ │ │ │ └── backup.ts
│ │ │ │ └── test/
│ │ │ │ └── electron-main/
│ │ │ │ └── backupMainService.test.ts
│ │ │ ├── checksum/
│ │ │ │ ├── common/
│ │ │ │ │ └── checksumService.ts
│ │ │ │ ├── node/
│ │ │ │ │ └── checksumService.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ ├── checksumService.test.ts
│ │ │ │ └── fixtures/
│ │ │ │ └── lorem.txt
│ │ │ ├── clipboard/
│ │ │ │ ├── browser/
│ │ │ │ │ └── clipboardService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── clipboardService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── testClipboardService.ts
│ │ │ ├── commands/
│ │ │ │ ├── common/
│ │ │ │ │ └── commands.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── commands.test.ts
│ │ │ │ └── nullCommandService.ts
│ │ │ ├── configuration/
│ │ │ │ ├── common/
│ │ │ │ │ ├── configuration.ts
│ │ │ │ │ ├── configurationModels.ts
│ │ │ │ │ ├── configurationRegistry.ts
│ │ │ │ │ ├── configurationService.ts
│ │ │ │ │ └── configurations.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── configuration.test.ts
│ │ │ │ ├── configurationModels.test.ts
│ │ │ │ ├── configurationRegistry.test.ts
│ │ │ │ ├── configurationService.test.ts
│ │ │ │ ├── configurations.test.ts
│ │ │ │ ├── policyConfiguration.test.ts
│ │ │ │ └── testConfigurationService.ts
│ │ │ ├── contextkey/
│ │ │ │ ├── browser/
│ │ │ │ │ └── contextKeyService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── contextkey.ts
│ │ │ │ │ ├── contextkeys.ts
│ │ │ │ │ └── scanner.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ └── contextkey.test.ts
│ │ │ │ └── common/
│ │ │ │ ├── contextkey.test.ts
│ │ │ │ ├── parser.test.ts
│ │ │ │ └── scanner.test.ts
│ │ │ ├── contextview/
│ │ │ │ └── browser/
│ │ │ │ ├── contextMenuHandler.ts
│ │ │ │ ├── contextMenuService.ts
│ │ │ │ ├── contextView.ts
│ │ │ │ └── contextViewService.ts
│ │ │ ├── cssDev/
│ │ │ │ └── node/
│ │ │ │ └── cssDevService.ts
│ │ │ ├── debug/
│ │ │ │ ├── common/
│ │ │ │ │ ├── extensionHostDebug.ts
│ │ │ │ │ └── extensionHostDebugIpc.ts
│ │ │ │ └── electron-main/
│ │ │ │ └── extensionHostDebugIpc.ts
│ │ │ ├── diagnostics/
│ │ │ │ ├── common/
│ │ │ │ │ └── diagnostics.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── diagnosticsMainService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── diagnosticsService.ts
│ │ │ │ └── node/
│ │ │ │ └── diagnosticsService.ts
│ │ │ ├── dialogs/
│ │ │ │ ├── browser/
│ │ │ │ │ └── dialog.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── dialogs.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── dialogMainService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── dialog.test.ts
│ │ │ │ └── testDialogService.ts
│ │ │ ├── dnd/
│ │ │ │ └── browser/
│ │ │ │ └── dnd.ts
│ │ │ ├── download/
│ │ │ │ └── common/
│ │ │ │ ├── download.ts
│ │ │ │ ├── downloadIpc.ts
│ │ │ │ └── downloadService.ts
│ │ │ ├── editor/
│ │ │ │ └── common/
│ │ │ │ └── editor.ts
│ │ │ ├── encryption/
│ │ │ │ ├── common/
│ │ │ │ │ └── encryptionService.ts
│ │ │ │ └── electron-main/
│ │ │ │ └── encryptionMainService.ts
│ │ │ ├── environment/
│ │ │ │ ├── common/
│ │ │ │ │ ├── argv.ts
│ │ │ │ │ ├── environment.ts
│ │ │ │ │ └── environmentService.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── environmentMainService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── argv.ts
│ │ │ │ │ ├── argvHelper.ts
│ │ │ │ │ ├── environmentService.ts
│ │ │ │ │ ├── stdin.ts
│ │ │ │ │ ├── userDataPath.ts
│ │ │ │ │ └── wait.ts
│ │ │ │ └── test/
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── environmentMainService.test.ts
│ │ │ │ └── node/
│ │ │ │ ├── argv.test.ts
│ │ │ │ ├── environmentService.test.ts
│ │ │ │ ├── nativeModules.integrationTest.ts
│ │ │ │ └── userDataPath.test.ts
│ │ │ ├── extensionManagement/
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractExtensionManagementService.ts
│ │ │ │ │ ├── allowedExtensionsService.ts
│ │ │ │ │ ├── configRemotes.ts
│ │ │ │ │ ├── extensionEnablementService.ts
│ │ │ │ │ ├── extensionGalleryManifest.ts
│ │ │ │ │ ├── extensionGalleryManifestService.ts
│ │ │ │ │ ├── extensionGalleryManifestServiceIpc.ts
│ │ │ │ │ ├── extensionGalleryService.ts
│ │ │ │ │ ├── extensionManagement.ts
│ │ │ │ │ ├── extensionManagementCLI.ts
│ │ │ │ │ ├── extensionManagementIpc.ts
│ │ │ │ │ ├── extensionManagementUtil.ts
│ │ │ │ │ ├── extensionNls.ts
│ │ │ │ │ ├── extensionStorage.ts
│ │ │ │ │ ├── extensionTipsService.ts
│ │ │ │ │ ├── extensionsProfileScannerService.ts
│ │ │ │ │ ├── extensionsScannerService.ts
│ │ │ │ │ ├── implicitActivationEvents.ts
│ │ │ │ │ └── unsupportedExtensionsMigration.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── extensionsProfileScannerService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── extensionDownloader.ts
│ │ │ │ │ ├── extensionLifecycle.ts
│ │ │ │ │ ├── extensionManagementService.ts
│ │ │ │ │ ├── extensionManagementUtil.ts
│ │ │ │ │ ├── extensionSignatureVerificationService.ts
│ │ │ │ │ ├── extensionTipsService.ts
│ │ │ │ │ ├── extensionsManifestCache.ts
│ │ │ │ │ ├── extensionsProfileScannerService.ts
│ │ │ │ │ ├── extensionsScannerService.ts
│ │ │ │ │ └── extensionsWatcher.ts
│ │ │ │ └── test/
│ │ │ │ ├── common/
│ │ │ │ │ ├── allowedExtensionsService.test.ts
│ │ │ │ │ ├── configRemotes.test.ts
│ │ │ │ │ ├── extensionGalleryService.test.ts
│ │ │ │ │ ├── extensionManagement.test.ts
│ │ │ │ │ ├── extensionNls.test.ts
│ │ │ │ │ └── extensionsProfileScannerService.test.ts
│ │ │ │ └── node/
│ │ │ │ ├── extensionDownloader.test.ts
│ │ │ │ └── extensionsScannerService.test.ts
│ │ │ ├── extensionRecommendations/
│ │ │ │ └── common/
│ │ │ │ ├── extensionRecommendations.ts
│ │ │ │ └── extensionRecommendationsIpc.ts
│ │ │ ├── extensionResourceLoader/
│ │ │ │ ├── browser/
│ │ │ │ │ └── extensionResourceLoaderService.ts
│ │ │ │ └── common/
│ │ │ │ ├── extensionResourceLoader.ts
│ │ │ │ └── extensionResourceLoaderService.ts
│ │ │ ├── extensions/
│ │ │ │ ├── common/
│ │ │ │ │ ├── extensionHostStarter.ts
│ │ │ │ │ ├── extensionValidator.ts
│ │ │ │ │ ├── extensions.ts
│ │ │ │ │ └── extensionsApiProposals.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── extensionHostStarter.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── extensionValidator.test.ts
│ │ │ │ └── extensions.test.ts
│ │ │ ├── externalServices/
│ │ │ │ └── common/
│ │ │ │ ├── marketplace.ts
│ │ │ │ └── serviceMachineId.ts
│ │ │ ├── externalTerminal/
│ │ │ │ ├── common/
│ │ │ │ │ └── externalTerminal.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── externalTerminal.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── externalTerminalService.ts
│ │ │ │ ├── node/
│ │ │ │ │ └── externalTerminalService.ts
│ │ │ │ └── test/
│ │ │ │ └── electron-main/
│ │ │ │ └── externalTerminalService.test.ts
│ │ │ ├── files/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── htmlFileSystemProvider.ts
│ │ │ │ │ ├── indexedDBFileSystemProvider.ts
│ │ │ │ │ └── webFileSystemAccess.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── diskFileSystemProvider.ts
│ │ │ │ │ ├── diskFileSystemProviderClient.ts
│ │ │ │ │ ├── fileService.ts
│ │ │ │ │ ├── files.ts
│ │ │ │ │ ├── inMemoryFilesystemProvider.ts
│ │ │ │ │ ├── io.ts
│ │ │ │ │ └── watcher.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── diskFileSystemProviderServer.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── diskFileSystemProvider.ts
│ │ │ │ │ ├── diskFileSystemProviderServer.ts
│ │ │ │ │ └── watcher/
│ │ │ │ │ ├── baseWatcher.ts
│ │ │ │ │ ├── nodejs/
│ │ │ │ │ │ ├── nodejsClient.ts
│ │ │ │ │ │ ├── nodejsWatcher.ts
│ │ │ │ │ │ └── nodejsWatcherLib.ts
│ │ │ │ │ ├── parcel/
│ │ │ │ │ │ └── parcelWatcher.ts
│ │ │ │ │ ├── watcher.ts
│ │ │ │ │ ├── watcherClient.ts
│ │ │ │ │ ├── watcherMain.ts
│ │ │ │ │ └── watcherStats.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── fileService.test.ts
│ │ │ │ │ └── indexedDBFileService.integrationTest.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── files.test.ts
│ │ │ │ │ ├── nullFileSystemProvider.ts
│ │ │ │ │ └── watcher.test.ts
│ │ │ │ └── node/
│ │ │ │ ├── diskFileService.integrationTest.ts
│ │ │ │ ├── fixtures/
│ │ │ │ │ ├── resolver/
│ │ │ │ │ │ ├── examples/
│ │ │ │ │ │ │ ├── company.js
│ │ │ │ │ │ │ ├── conway.js
│ │ │ │ │ │ │ ├── employee.js
│ │ │ │ │ │ │ └── small.js
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── other/
│ │ │ │ │ │ │ └── deep/
│ │ │ │ │ │ │ ├── company.js
│ │ │ │ │ │ │ ├── conway.js
│ │ │ │ │ │ │ ├── employee.js
│ │ │ │ │ │ │ └── small.js
│ │ │ │ │ │ └── site.css
│ │ │ │ │ └── service/
│ │ │ │ │ ├── binary.txt
│ │ │ │ │ ├── deep/
│ │ │ │ │ │ ├── company.js
│ │ │ │ │ │ ├── conway.js
│ │ │ │ │ │ ├── employee.js
│ │ │ │ │ │ └── small.js
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── lorem.txt
│ │ │ │ │ ├── small.txt
│ │ │ │ │ ├── small_umlaut.txt
│ │ │ │ │ ├── some_utf16le.css
│ │ │ │ │ └── some_utf8_bom.txt
│ │ │ │ ├── nodejsWatcher.test.ts
│ │ │ │ └── parcelWatcher.test.ts
│ │ │ ├── history/
│ │ │ │ └── browser/
│ │ │ │ ├── contextScopedHistoryWidget.ts
│ │ │ │ └── historyWidgetKeybindingHint.ts
│ │ │ ├── hover/
│ │ │ │ ├── browser/
│ │ │ │ │ └── hover.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── nullHoverService.ts
│ │ │ ├── instantiation/
│ │ │ │ ├── common/
│ │ │ │ │ ├── descriptors.ts
│ │ │ │ │ ├── extensions.ts
│ │ │ │ │ ├── graph.ts
│ │ │ │ │ ├── instantiation.ts
│ │ │ │ │ ├── instantiationService.ts
│ │ │ │ │ └── serviceCollection.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── graph.test.ts
│ │ │ │ ├── instantiationService.test.ts
│ │ │ │ └── instantiationServiceMock.ts
│ │ │ ├── ipc/
│ │ │ │ ├── common/
│ │ │ │ │ ├── mainProcessService.ts
│ │ │ │ │ └── services.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── mainProcessService.ts
│ │ │ │ └── services.ts
│ │ │ ├── jsonschemas/
│ │ │ │ └── common/
│ │ │ │ └── jsonContributionRegistry.ts
│ │ │ ├── keybinding/
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractKeybindingService.ts
│ │ │ │ │ ├── baseResolvedKeybinding.ts
│ │ │ │ │ ├── keybinding.ts
│ │ │ │ │ ├── keybindingResolver.ts
│ │ │ │ │ ├── keybindingsRegistry.ts
│ │ │ │ │ ├── resolvedKeybindingItem.ts
│ │ │ │ │ └── usLayoutResolvedKeybinding.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── abstractKeybindingService.test.ts
│ │ │ │ ├── keybindingLabels.test.ts
│ │ │ │ ├── keybindingResolver.test.ts
│ │ │ │ ├── keybindingsTestUtils.ts
│ │ │ │ └── mockKeybindingService.ts
│ │ │ ├── keyboardLayout/
│ │ │ │ ├── common/
│ │ │ │ │ ├── keyboardConfig.ts
│ │ │ │ │ ├── keyboardLayout.ts
│ │ │ │ │ ├── keyboardLayoutService.ts
│ │ │ │ │ └── keyboardMapper.ts
│ │ │ │ └── electron-main/
│ │ │ │ └── keyboardLayoutMainService.ts
│ │ │ ├── label/
│ │ │ │ └── common/
│ │ │ │ └── label.ts
│ │ │ ├── languagePacks/
│ │ │ │ ├── browser/
│ │ │ │ │ └── languagePacks.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── languagePacks.ts
│ │ │ │ │ └── localizedStrings.ts
│ │ │ │ └── node/
│ │ │ │ └── languagePacks.ts
│ │ │ ├── launch/
│ │ │ │ └── electron-main/
│ │ │ │ └── launchMainService.ts
│ │ │ ├── layout/
│ │ │ │ └── browser/
│ │ │ │ ├── layoutService.ts
│ │ │ │ └── zIndexRegistry.ts
│ │ │ ├── lifecycle/
│ │ │ │ ├── common/
│ │ │ │ │ └── lifecycle.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── lifecycleMainService.ts
│ │ │ │ └── node/
│ │ │ │ └── sharedProcessLifecycleService.ts
│ │ │ ├── list/
│ │ │ │ └── browser/
│ │ │ │ └── listService.ts
│ │ │ ├── log/
│ │ │ │ ├── browser/
│ │ │ │ │ └── log.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── bufferLog.ts
│ │ │ │ │ ├── fileLog.ts
│ │ │ │ │ ├── log.ts
│ │ │ │ │ ├── logIpc.ts
│ │ │ │ │ └── logService.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── logIpc.ts
│ │ │ │ │ └── loggerService.ts
│ │ │ │ └── node/
│ │ │ │ ├── loggerService.ts
│ │ │ │ └── spdlogLog.ts
│ │ │ ├── markers/
│ │ │ │ ├── common/
│ │ │ │ │ ├── markerService.ts
│ │ │ │ │ └── markers.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── markerService.test.ts
│ │ │ ├── mcp/
│ │ │ │ ├── common/
│ │ │ │ │ ├── mcpManagementCli.ts
│ │ │ │ │ ├── mcpPlatformTypes.ts
│ │ │ │ │ └── nativeMcpDiscoveryHelper.ts
│ │ │ │ └── node/
│ │ │ │ ├── nativeMcpDiscoveryHelperChannel.ts
│ │ │ │ └── nativeMcpDiscoveryHelperService.ts
│ │ │ ├── menubar/
│ │ │ │ ├── common/
│ │ │ │ │ └── menubar.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── menubar.ts
│ │ │ │ │ └── menubarMainService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── menubar.ts
│ │ │ ├── native/
│ │ │ │ ├── common/
│ │ │ │ │ ├── native.ts
│ │ │ │ │ └── nativeHostService.ts
│ │ │ │ └── electron-main/
│ │ │ │ ├── auth.ts
│ │ │ │ └── nativeHostMainService.ts
│ │ │ ├── notification/
│ │ │ │ ├── common/
│ │ │ │ │ └── notification.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── testNotificationService.ts
│ │ │ ├── observable/
│ │ │ │ └── common/
│ │ │ │ ├── observableMemento.ts
│ │ │ │ ├── platformObservableUtils.ts
│ │ │ │ ├── wrapInHotClass.ts
│ │ │ │ └── wrapInReloadableClass.ts
│ │ │ ├── opener/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── link.css
│ │ │ │ │ └── link.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── opener.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── nullOpenerService.ts
│ │ │ │ └── opener.test.ts
│ │ │ ├── policy/
│ │ │ │ ├── common/
│ │ │ │ │ ├── filePolicyService.ts
│ │ │ │ │ ├── policy.ts
│ │ │ │ │ └── policyIpc.ts
│ │ │ │ └── node/
│ │ │ │ └── nativePolicyService.ts
│ │ │ ├── process/
│ │ │ │ ├── common/
│ │ │ │ │ └── process.ts
│ │ │ │ └── electron-main/
│ │ │ │ └── processMainService.ts
│ │ │ ├── product/
│ │ │ │ └── common/
│ │ │ │ ├── product.ts
│ │ │ │ └── productService.ts
│ │ │ ├── profiling/
│ │ │ │ ├── common/
│ │ │ │ │ ├── profiling.ts
│ │ │ │ │ ├── profilingModel.ts
│ │ │ │ │ └── profilingTelemetrySpec.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── windowProfiling.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── profileAnalysisWorker.ts
│ │ │ │ │ ├── profileAnalysisWorkerMain.ts
│ │ │ │ │ ├── profileAnalysisWorkerService.ts
│ │ │ │ │ └── profilingService.ts
│ │ │ │ └── node/
│ │ │ │ └── profilingService.ts
│ │ │ ├── progress/
│ │ │ │ ├── common/
│ │ │ │ │ └── progress.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── progress.test.ts
│ │ │ ├── prompts/
│ │ │ │ ├── common/
│ │ │ │ │ ├── config.ts
│ │ │ │ │ └── constants.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── config.test.ts
│ │ │ │ ├── constants.test.ts
│ │ │ │ └── utils/
│ │ │ │ ├── mock.test.ts
│ │ │ │ └── mock.ts
│ │ │ ├── protocol/
│ │ │ │ └── electron-main/
│ │ │ │ ├── protocol.ts
│ │ │ │ └── protocolMainService.ts
│ │ │ ├── quickinput/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── commandsQuickAccess.ts
│ │ │ │ │ ├── helpQuickAccess.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── quickInput.css
│ │ │ │ │ ├── pickerQuickAccess.ts
│ │ │ │ │ ├── quickAccess.ts
│ │ │ │ │ ├── quickInput.ts
│ │ │ │ │ ├── quickInputActions.ts
│ │ │ │ │ ├── quickInputBox.ts
│ │ │ │ │ ├── quickInputController.ts
│ │ │ │ │ ├── quickInputService.ts
│ │ │ │ │ ├── quickInputTree.ts
│ │ │ │ │ ├── quickInputUtils.ts
│ │ │ │ │ └── quickPickPin.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── quickAccess.ts
│ │ │ │ │ └── quickInput.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── quickinput.test.ts
│ │ │ ├── registry/
│ │ │ │ ├── common/
│ │ │ │ │ └── platform.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── platform.test.ts
│ │ │ ├── remote/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserSocketFactory.ts
│ │ │ │ │ └── remoteAuthorityResolverService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── electronRemoteResources.ts
│ │ │ │ │ ├── managedSocket.ts
│ │ │ │ │ ├── remote.ts
│ │ │ │ │ ├── remoteAgentConnection.ts
│ │ │ │ │ ├── remoteAgentEnvironment.ts
│ │ │ │ │ ├── remoteAuthorityResolver.ts
│ │ │ │ │ ├── remoteExtensionsScanner.ts
│ │ │ │ │ ├── remoteHosts.ts
│ │ │ │ │ ├── remoteSocketFactoryService.ts
│ │ │ │ │ └── sharedProcessTunnelService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── electronRemoteResourceLoader.ts
│ │ │ │ │ ├── remoteAuthorityResolverService.ts
│ │ │ │ │ └── sharedProcessTunnelService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── nodeSocketFactory.ts
│ │ │ │ │ └── wsl.ts
│ │ │ │ └── test/
│ │ │ │ ├── common/
│ │ │ │ │ └── remoteHosts.test.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── remoteAuthorityResolverService.test.ts
│ │ │ ├── remoteTunnel/
│ │ │ │ ├── common/
│ │ │ │ │ └── remoteTunnel.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── remoteTunnelService.ts
│ │ │ │ └── node/
│ │ │ │ └── remoteTunnelService.ts
│ │ │ ├── request/
│ │ │ │ ├── common/
│ │ │ │ │ ├── request.ts
│ │ │ │ │ └── requestIpc.ts
│ │ │ │ ├── electron-utility/
│ │ │ │ │ └── requestService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── proxy.ts
│ │ │ │ │ └── requestService.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ └── requestService.test.ts
│ │ │ ├── secrets/
│ │ │ │ ├── common/
│ │ │ │ │ └── secrets.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── secrets.test.ts
│ │ │ │ └── testSecretStorageService.ts
│ │ │ ├── sharedProcess/
│ │ │ │ ├── common/
│ │ │ │ │ └── sharedProcess.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── sharedProcess.ts
│ │ │ │ └── node/
│ │ │ │ └── sharedProcess.ts
│ │ │ ├── shell/
│ │ │ │ └── node/
│ │ │ │ └── shellEnv.ts
│ │ │ ├── sign/
│ │ │ │ ├── browser/
│ │ │ │ │ └── signService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractSignService.ts
│ │ │ │ │ └── sign.ts
│ │ │ │ └── node/
│ │ │ │ └── signService.ts
│ │ │ ├── state/
│ │ │ │ ├── node/
│ │ │ │ │ ├── state.ts
│ │ │ │ │ └── stateService.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ └── state.test.ts
│ │ │ ├── storage/
│ │ │ │ ├── common/
│ │ │ │ │ ├── storage.ts
│ │ │ │ │ ├── storageIpc.ts
│ │ │ │ │ └── storageService.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── storageIpc.ts
│ │ │ │ │ ├── storageMain.ts
│ │ │ │ │ └── storageMainService.ts
│ │ │ │ └── test/
│ │ │ │ ├── common/
│ │ │ │ │ └── storageService.test.ts
│ │ │ │ └── electron-main/
│ │ │ │ └── storageMainService.test.ts
│ │ │ ├── telemetry/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── 1dsAppender.ts
│ │ │ │ │ └── errorTelemetry.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── 1dsAppender.ts
│ │ │ │ │ ├── commonProperties.ts
│ │ │ │ │ ├── errorTelemetry.ts
│ │ │ │ │ ├── gdprTypings.ts
│ │ │ │ │ ├── remoteTelemetryChannel.ts
│ │ │ │ │ ├── serverTelemetryService.ts
│ │ │ │ │ ├── telemetry.ts
│ │ │ │ │ ├── telemetryIpc.ts
│ │ │ │ │ ├── telemetryLogAppender.ts
│ │ │ │ │ ├── telemetryService.ts
│ │ │ │ │ └── telemetryUtils.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── errorTelemetry.ts
│ │ │ │ │ └── telemetryUtils.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── customEndpointTelemetryService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── 1dsAppender.ts
│ │ │ │ │ ├── customEndpointTelemetryService.ts
│ │ │ │ │ ├── errorTelemetry.ts
│ │ │ │ │ ├── telemetry.ts
│ │ │ │ │ └── telemetryUtils.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── 1dsAppender.test.ts
│ │ │ │ │ └── telemetryService.test.ts
│ │ │ │ └── common/
│ │ │ │ └── telemetryLogAppender.test.ts
│ │ │ ├── terminal/
│ │ │ │ ├── common/
│ │ │ │ │ ├── capabilities/
│ │ │ │ │ │ ├── bufferMarkCapability.ts
│ │ │ │ │ │ ├── capabilities.ts
│ │ │ │ │ │ ├── commandDetection/
│ │ │ │ │ │ │ ├── promptInputModel.ts
│ │ │ │ │ │ │ └── terminalCommand.ts
│ │ │ │ │ │ ├── commandDetectionCapability.ts
│ │ │ │ │ │ ├── cwdDetectionCapability.ts
│ │ │ │ │ │ ├── naiveCwdDetectionCapability.ts
│ │ │ │ │ │ ├── partialCommandDetectionCapability.ts
│ │ │ │ │ │ ├── shellEnvDetectionCapability.ts
│ │ │ │ │ │ └── terminalCapabilityStore.ts
│ │ │ │ │ ├── environmentVariable.ts
│ │ │ │ │ ├── environmentVariableCollection.ts
│ │ │ │ │ ├── environmentVariableShared.ts
│ │ │ │ │ ├── requestStore.ts
│ │ │ │ │ ├── terminal.ts
│ │ │ │ │ ├── terminalDataBuffering.ts
│ │ │ │ │ ├── terminalEnvironment.ts
│ │ │ │ │ ├── terminalLogService.ts
│ │ │ │ │ ├── terminalPlatformConfiguration.ts
│ │ │ │ │ ├── terminalProcess.ts
│ │ │ │ │ ├── terminalProfiles.ts
│ │ │ │ │ ├── terminalRecorder.ts
│ │ │ │ │ ├── terminalStrings.ts
│ │ │ │ │ └── xterm/
│ │ │ │ │ └── shellIntegrationAddon.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── electronPtyHostStarter.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── childProcessMonitor.ts
│ │ │ │ │ ├── heartbeatService.ts
│ │ │ │ │ ├── nodePtyHostStarter.ts
│ │ │ │ │ ├── ptyHost.ts
│ │ │ │ │ ├── ptyHostMain.ts
│ │ │ │ │ ├── ptyHostService.ts
│ │ │ │ │ ├── ptyService.ts
│ │ │ │ │ ├── terminalContrib/
│ │ │ │ │ │ └── autoReplies/
│ │ │ │ │ │ ├── autoRepliesContribController.ts
│ │ │ │ │ │ └── terminalAutoResponder.ts
│ │ │ │ │ ├── terminalEnvironment.ts
│ │ │ │ │ ├── terminalProcess.ts
│ │ │ │ │ ├── terminalProfiles.ts
│ │ │ │ │ └── windowsShellHelper.ts
│ │ │ │ └── test/
│ │ │ │ ├── common/
│ │ │ │ │ ├── capabilities/
│ │ │ │ │ │ └── commandDetection/
│ │ │ │ │ │ └── promptInputModel.test.ts
│ │ │ │ │ ├── requestStore.test.ts
│ │ │ │ │ ├── terminalEnvironment.test.ts
│ │ │ │ │ ├── terminalProcess.test.ts
│ │ │ │ │ ├── terminalProfiles.test.ts
│ │ │ │ │ └── terminalRecorder.test.ts
│ │ │ │ └── node/
│ │ │ │ └── terminalEnvironment.test.ts
│ │ │ ├── test/
│ │ │ │ └── electron-main/
│ │ │ │ └── workbenchTestServices.ts
│ │ │ ├── theme/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── defaultStyles.ts
│ │ │ │ │ └── iconsStyleSheet.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── colorRegistry.ts
│ │ │ │ │ ├── colorUtils.ts
│ │ │ │ │ ├── colors/
│ │ │ │ │ │ ├── baseColors.ts
│ │ │ │ │ │ ├── chartsColors.ts
│ │ │ │ │ │ ├── editorColors.ts
│ │ │ │ │ │ ├── inputColors.ts
│ │ │ │ │ │ ├── listColors.ts
│ │ │ │ │ │ ├── menuColors.ts
│ │ │ │ │ │ ├── minimapColors.ts
│ │ │ │ │ │ ├── miscColors.ts
│ │ │ │ │ │ ├── quickpickColors.ts
│ │ │ │ │ │ └── searchColors.ts
│ │ │ │ │ ├── iconRegistry.ts
│ │ │ │ │ ├── theme.ts
│ │ │ │ │ ├── themeService.ts
│ │ │ │ │ └── tokenClassificationRegistry.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── themeMainService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── testThemeService.ts
│ │ │ ├── tunnel/
│ │ │ │ ├── common/
│ │ │ │ │ └── tunnel.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── sharedProcessTunnelService.ts
│ │ │ │ │ └── tunnelService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── tunnel.test.ts
│ │ │ ├── undoRedo/
│ │ │ │ ├── common/
│ │ │ │ │ ├── undoRedo.ts
│ │ │ │ │ └── undoRedoService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── undoRedoService.test.ts
│ │ │ ├── update/
│ │ │ │ ├── common/
│ │ │ │ │ ├── update.config.contribution.ts
│ │ │ │ │ ├── update.ts
│ │ │ │ │ └── updateIpc.ts
│ │ │ │ └── electron-main/
│ │ │ │ ├── abstractUpdateService.ts
│ │ │ │ ├── updateService.darwin.ts
│ │ │ │ ├── updateService.linux.ts
│ │ │ │ ├── updateService.snap.ts
│ │ │ │ └── updateService.win32.ts
│ │ │ ├── uriIdentity/
│ │ │ │ ├── common/
│ │ │ │ │ ├── uriIdentity.ts
│ │ │ │ │ └── uriIdentityService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── uriIdentityService.test.ts
│ │ │ ├── url/
│ │ │ │ ├── common/
│ │ │ │ │ ├── url.ts
│ │ │ │ │ ├── urlIpc.ts
│ │ │ │ │ └── urlService.ts
│ │ │ │ └── electron-main/
│ │ │ │ ├── electronUrlListener.ts
│ │ │ │ └── url.ts
│ │ │ ├── userData/
│ │ │ │ ├── common/
│ │ │ │ │ └── fileUserDataProvider.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── fileUserDataProvider.test.ts
│ │ │ ├── userDataProfile/
│ │ │ │ ├── browser/
│ │ │ │ │ └── userDataProfile.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── userDataProfile.ts
│ │ │ │ │ ├── userDataProfileIpc.ts
│ │ │ │ │ └── userDataProfileStorageService.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── userDataProfile.ts
│ │ │ │ │ ├── userDataProfileStorageIpc.ts
│ │ │ │ │ └── userDataProfilesHandler.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── userDataProfileStorageService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── userDataProfile.ts
│ │ │ │ │ └── userDataProfileStorageService.ts
│ │ │ │ └── test/
│ │ │ │ ├── common/
│ │ │ │ │ ├── userDataProfileService.test.ts
│ │ │ │ │ └── userDataProfileStorageService.test.ts
│ │ │ │ └── electron-main/
│ │ │ │ └── userDataProfileMainService.test.ts
│ │ │ ├── userDataSync/
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractSynchronizer.ts
│ │ │ │ │ ├── content.ts
│ │ │ │ │ ├── extensionsMerge.ts
│ │ │ │ │ ├── extensionsSync.ts
│ │ │ │ │ ├── globalStateMerge.ts
│ │ │ │ │ ├── globalStateSync.ts
│ │ │ │ │ ├── ignoredExtensions.ts
│ │ │ │ │ ├── keybindingsMerge.ts
│ │ │ │ │ ├── keybindingsSync.ts
│ │ │ │ │ ├── promptsSync/
│ │ │ │ │ │ ├── promptsMerge.ts
│ │ │ │ │ │ └── promptsSync.ts
│ │ │ │ │ ├── settingsMerge.ts
│ │ │ │ │ ├── settingsSync.ts
│ │ │ │ │ ├── snippetsMerge.ts
│ │ │ │ │ ├── snippetsSync.ts
│ │ │ │ │ ├── tasksSync.ts
│ │ │ │ │ ├── userDataAutoSyncService.ts
│ │ │ │ │ ├── userDataProfilesManifestMerge.ts
│ │ │ │ │ ├── userDataProfilesManifestSync.ts
│ │ │ │ │ ├── userDataSync.ts
│ │ │ │ │ ├── userDataSyncAccount.ts
│ │ │ │ │ ├── userDataSyncEnablementService.ts
│ │ │ │ │ ├── userDataSyncIpc.ts
│ │ │ │ │ ├── userDataSyncLocalStoreService.ts
│ │ │ │ │ ├── userDataSyncLog.ts
│ │ │ │ │ ├── userDataSyncMachines.ts
│ │ │ │ │ ├── userDataSyncResourceProvider.ts
│ │ │ │ │ ├── userDataSyncService.ts
│ │ │ │ │ ├── userDataSyncServiceIpc.ts
│ │ │ │ │ └── userDataSyncStoreService.ts
│ │ │ │ ├── node/
│ │ │ │ │ └── userDataAutoSyncService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── extensionsMerge.test.ts
│ │ │ │ ├── globalStateMerge.test.ts
│ │ │ │ ├── globalStateSync.test.ts
│ │ │ │ ├── keybindingsMerge.test.ts
│ │ │ │ ├── keybindingsSync.test.ts
│ │ │ │ ├── promptsSync/
│ │ │ │ │ └── promptsSync.test.ts
│ │ │ │ ├── settingsMerge.test.ts
│ │ │ │ ├── settingsSync.test.ts
│ │ │ │ ├── snippetsMerge.test.ts
│ │ │ │ ├── snippetsSync.test.ts
│ │ │ │ ├── synchronizer.test.ts
│ │ │ │ ├── tasksSync.test.ts
│ │ │ │ ├── userDataAutoSyncService.test.ts
│ │ │ │ ├── userDataProfilesManifestMerge.test.ts
│ │ │ │ ├── userDataProfilesManifestSync.test.ts
│ │ │ │ ├── userDataSyncClient.ts
│ │ │ │ ├── userDataSyncService.test.ts
│ │ │ │ └── userDataSyncStoreService.test.ts
│ │ │ ├── utilityProcess/
│ │ │ │ ├── common/
│ │ │ │ │ └── utilityProcessWorkerService.ts
│ │ │ │ └── electron-main/
│ │ │ │ ├── utilityProcess.ts
│ │ │ │ └── utilityProcessWorkerMainService.ts
│ │ │ ├── webContentExtractor/
│ │ │ │ ├── common/
│ │ │ │ │ └── webContentExtractor.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── cdpAccessibilityDomain.ts
│ │ │ │ │ └── webContentExtractorService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── webContentExtractorService.ts
│ │ │ │ └── node/
│ │ │ │ └── sharedWebContentExtractorService.ts
│ │ │ ├── webview/
│ │ │ │ ├── common/
│ │ │ │ │ ├── mimeTypes.ts
│ │ │ │ │ ├── webviewManagerService.ts
│ │ │ │ │ └── webviewPortMapping.ts
│ │ │ │ └── electron-main/
│ │ │ │ ├── webviewMainService.ts
│ │ │ │ └── webviewProtocolProvider.ts
│ │ │ ├── window/
│ │ │ │ ├── common/
│ │ │ │ │ └── window.ts
│ │ │ │ ├── electron-main/
│ │ │ │ │ └── window.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── window.ts
│ │ │ ├── windows/
│ │ │ │ ├── electron-main/
│ │ │ │ │ ├── windowImpl.ts
│ │ │ │ │ ├── windows.ts
│ │ │ │ │ ├── windowsFinder.ts
│ │ │ │ │ ├── windowsMainService.ts
│ │ │ │ │ └── windowsStateHandler.ts
│ │ │ │ ├── node/
│ │ │ │ │ └── windowTracker.ts
│ │ │ │ └── test/
│ │ │ │ └── electron-main/
│ │ │ │ ├── windowsFinder.test.ts
│ │ │ │ └── windowsStateHandler.test.ts
│ │ │ ├── workspace/
│ │ │ │ ├── common/
│ │ │ │ │ ├── canonicalUri.ts
│ │ │ │ │ ├── editSessions.ts
│ │ │ │ │ ├── virtualWorkspace.ts
│ │ │ │ │ ├── workspace.ts
│ │ │ │ │ └── workspaceTrust.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── testWorkspace.ts
│ │ │ │ └── workspace.test.ts
│ │ │ └── workspaces/
│ │ │ ├── common/
│ │ │ │ └── workspaces.ts
│ │ │ ├── electron-main/
│ │ │ │ ├── workspacesHistoryMainService.ts
│ │ │ │ ├── workspacesMainService.ts
│ │ │ │ └── workspacesManagementMainService.ts
│ │ │ ├── node/
│ │ │ │ └── workspaces.ts
│ │ │ └── test/
│ │ │ ├── common/
│ │ │ │ └── workspaces.test.ts
│ │ │ └── electron-main/
│ │ │ ├── workspaces.test.ts
│ │ │ ├── workspacesHistoryStorage.test.ts
│ │ │ └── workspacesManagementMainService.test.ts
│ │ ├── server/
│ │ │ ├── node/
│ │ │ │ ├── extensionHostConnection.ts
│ │ │ │ ├── extensionHostStatusService.ts
│ │ │ │ ├── extensionsScannerService.ts
│ │ │ │ ├── remoteAgentEnvironmentImpl.ts
│ │ │ │ ├── remoteExtensionHostAgentCli.ts
│ │ │ │ ├── remoteExtensionHostAgentServer.ts
│ │ │ │ ├── remoteExtensionManagement.ts
│ │ │ │ ├── remoteExtensionsScanner.ts
│ │ │ │ ├── remoteFileSystemProviderServer.ts
│ │ │ │ ├── remoteLanguagePacks.ts
│ │ │ │ ├── remoteTerminalChannel.ts
│ │ │ │ ├── server.cli.ts
│ │ │ │ ├── server.main.ts
│ │ │ │ ├── serverConnectionToken.ts
│ │ │ │ ├── serverEnvironmentService.ts
│ │ │ │ ├── serverServices.ts
│ │ │ │ └── webClientServer.ts
│ │ │ └── test/
│ │ │ └── node/
│ │ │ └── serverConnectionToken.test.ts
│ │ └── workbench/
│ │ ├── api/
│ │ │ ├── browser/
│ │ │ │ ├── extensionHost.contribution.ts
│ │ │ │ ├── mainThreadAiEmbeddingVector.ts
│ │ │ │ ├── mainThreadAiRelatedInformation.ts
│ │ │ │ ├── mainThreadAuthentication.ts
│ │ │ │ ├── mainThreadBulkEdits.ts
│ │ │ │ ├── mainThreadCLICommands.ts
│ │ │ │ ├── mainThreadChatAgents2.ts
│ │ │ │ ├── mainThreadChatCodeMapper.ts
│ │ │ │ ├── mainThreadChatStatus.ts
│ │ │ │ ├── mainThreadClipboard.ts
│ │ │ │ ├── mainThreadCodeInsets.ts
│ │ │ │ ├── mainThreadCommands.ts
│ │ │ │ ├── mainThreadComments.ts
│ │ │ │ ├── mainThreadConfiguration.ts
│ │ │ │ ├── mainThreadConsole.ts
│ │ │ │ ├── mainThreadCustomEditors.ts
│ │ │ │ ├── mainThreadDebugService.ts
│ │ │ │ ├── mainThreadDecorations.ts
│ │ │ │ ├── mainThreadDiagnostics.ts
│ │ │ │ ├── mainThreadDialogs.ts
│ │ │ │ ├── mainThreadDocumentContentProviders.ts
│ │ │ │ ├── mainThreadDocuments.ts
│ │ │ │ ├── mainThreadDocumentsAndEditors.ts
│ │ │ │ ├── mainThreadDownloadService.ts
│ │ │ │ ├── mainThreadEditSessionIdentityParticipant.ts
│ │ │ │ ├── mainThreadEditor.ts
│ │ │ │ ├── mainThreadEditorTabs.ts
│ │ │ │ ├── mainThreadEditors.ts
│ │ │ │ ├── mainThreadEmbeddings.ts
│ │ │ │ ├── mainThreadErrors.ts
│ │ │ │ ├── mainThreadExtensionService.ts
│ │ │ │ ├── mainThreadFileSystem.ts
│ │ │ │ ├── mainThreadFileSystemEventService.ts
│ │ │ │ ├── mainThreadInteractive.ts
│ │ │ │ ├── mainThreadLabelService.ts
│ │ │ │ ├── mainThreadLanguageFeatures.ts
│ │ │ │ ├── mainThreadLanguageModelTools.ts
│ │ │ │ ├── mainThreadLanguageModels.ts
│ │ │ │ ├── mainThreadLanguages.ts
│ │ │ │ ├── mainThreadLocalization.ts
│ │ │ │ ├── mainThreadLogService.ts
│ │ │ │ ├── mainThreadManagedSockets.ts
│ │ │ │ ├── mainThreadMcp.ts
│ │ │ │ ├── mainThreadMessageService.ts
│ │ │ │ ├── mainThreadNotebook.ts
│ │ │ │ ├── mainThreadNotebookDocuments.ts
│ │ │ │ ├── mainThreadNotebookDocumentsAndEditors.ts
│ │ │ │ ├── mainThreadNotebookDto.ts
│ │ │ │ ├── mainThreadNotebookEditors.ts
│ │ │ │ ├── mainThreadNotebookKernels.ts
│ │ │ │ ├── mainThreadNotebookRenderers.ts
│ │ │ │ ├── mainThreadNotebookSaveParticipant.ts
│ │ │ │ ├── mainThreadOutputService.ts
│ │ │ │ ├── mainThreadProfileContentHandlers.ts
│ │ │ │ ├── mainThreadProgress.ts
│ │ │ │ ├── mainThreadQuickDiff.ts
│ │ │ │ ├── mainThreadQuickOpen.ts
│ │ │ │ ├── mainThreadRemoteConnectionData.ts
│ │ │ │ ├── mainThreadSCM.ts
│ │ │ │ ├── mainThreadSaveParticipant.ts
│ │ │ │ ├── mainThreadSearch.ts
│ │ │ │ ├── mainThreadSecretState.ts
│ │ │ │ ├── mainThreadShare.ts
│ │ │ │ ├── mainThreadSpeech.ts
│ │ │ │ ├── mainThreadStatusBar.ts
│ │ │ │ ├── mainThreadStorage.ts
│ │ │ │ ├── mainThreadTask.ts
│ │ │ │ ├── mainThreadTelemetry.ts
│ │ │ │ ├── mainThreadTerminalService.ts
│ │ │ │ ├── mainThreadTerminalShellIntegration.ts
│ │ │ │ ├── mainThreadTesting.ts
│ │ │ │ ├── mainThreadTheming.ts
│ │ │ │ ├── mainThreadTimeline.ts
│ │ │ │ ├── mainThreadTreeViews.ts
│ │ │ │ ├── mainThreadTunnelService.ts
│ │ │ │ ├── mainThreadUriOpeners.ts
│ │ │ │ ├── mainThreadUrls.ts
│ │ │ │ ├── mainThreadWebviewManager.ts
│ │ │ │ ├── mainThreadWebviewPanels.ts
│ │ │ │ ├── mainThreadWebviewViews.ts
│ │ │ │ ├── mainThreadWebviews.ts
│ │ │ │ ├── mainThreadWindow.ts
│ │ │ │ ├── mainThreadWorkspace.ts
│ │ │ │ ├── statusBarExtensionPoint.ts
│ │ │ │ └── viewsExtensionPoint.ts
│ │ │ ├── common/
│ │ │ │ ├── cache.ts
│ │ │ │ ├── configurationExtensionPoint.ts
│ │ │ │ ├── extHost.api.impl.ts
│ │ │ │ ├── extHost.common.services.ts
│ │ │ │ ├── extHost.protocol.ts
│ │ │ │ ├── extHostAiRelatedInformation.ts
│ │ │ │ ├── extHostApiCommands.ts
│ │ │ │ ├── extHostApiDeprecationService.ts
│ │ │ │ ├── extHostAuthentication.ts
│ │ │ │ ├── extHostBulkEdits.ts
│ │ │ │ ├── extHostChatAgents2.ts
│ │ │ │ ├── extHostChatStatus.ts
│ │ │ │ ├── extHostClipboard.ts
│ │ │ │ ├── extHostCodeInsets.ts
│ │ │ │ ├── extHostCodeMapper.ts
│ │ │ │ ├── extHostCommands.ts
│ │ │ │ ├── extHostComments.ts
│ │ │ │ ├── extHostConfiguration.ts
│ │ │ │ ├── extHostConsoleForwarder.ts
│ │ │ │ ├── extHostCustomEditors.ts
│ │ │ │ ├── extHostDebugService.ts
│ │ │ │ ├── extHostDecorations.ts
│ │ │ │ ├── extHostDiagnostics.ts
│ │ │ │ ├── extHostDialogs.ts
│ │ │ │ ├── extHostDocumentContentProviders.ts
│ │ │ │ ├── extHostDocumentData.ts
│ │ │ │ ├── extHostDocumentSaveParticipant.ts
│ │ │ │ ├── extHostDocuments.ts
│ │ │ │ ├── extHostDocumentsAndEditors.ts
│ │ │ │ ├── extHostEditorTabs.ts
│ │ │ │ ├── extHostEmbedding.ts
│ │ │ │ ├── extHostEmbeddingVector.ts
│ │ │ │ ├── extHostExtensionActivator.ts
│ │ │ │ ├── extHostExtensionService.ts
│ │ │ │ ├── extHostFileSystem.ts
│ │ │ │ ├── extHostFileSystemConsumer.ts
│ │ │ │ ├── extHostFileSystemEventService.ts
│ │ │ │ ├── extHostFileSystemInfo.ts
│ │ │ │ ├── extHostInitDataService.ts
│ │ │ │ ├── extHostInteractive.ts
│ │ │ │ ├── extHostLabelService.ts
│ │ │ │ ├── extHostLanguageFeatures.ts
│ │ │ │ ├── extHostLanguageModelTools.ts
│ │ │ │ ├── extHostLanguageModels.ts
│ │ │ │ ├── extHostLanguages.ts
│ │ │ │ ├── extHostLocalizationService.ts
│ │ │ │ ├── extHostLogService.ts
│ │ │ │ ├── extHostLoggerService.ts
│ │ │ │ ├── extHostManagedSockets.ts
│ │ │ │ ├── extHostMcp.ts
│ │ │ │ ├── extHostMemento.ts
│ │ │ │ ├── extHostMessageService.ts
│ │ │ │ ├── extHostNotebook.ts
│ │ │ │ ├── extHostNotebookDocument.ts
│ │ │ │ ├── extHostNotebookDocumentSaveParticipant.ts
│ │ │ │ ├── extHostNotebookDocuments.ts
│ │ │ │ ├── extHostNotebookEditor.ts
│ │ │ │ ├── extHostNotebookEditors.ts
│ │ │ │ ├── extHostNotebookKernels.ts
│ │ │ │ ├── extHostNotebookRenderers.ts
│ │ │ │ ├── extHostOutput.ts
│ │ │ │ ├── extHostProfileContentHandler.ts
│ │ │ │ ├── extHostProgress.ts
│ │ │ │ ├── extHostQuickDiff.ts
│ │ │ │ ├── extHostQuickOpen.ts
│ │ │ │ ├── extHostRequireInterceptor.ts
│ │ │ │ ├── extHostRpcService.ts
│ │ │ │ ├── extHostSCM.ts
│ │ │ │ ├── extHostSearch.ts
│ │ │ │ ├── extHostSecretState.ts
│ │ │ │ ├── extHostSecrets.ts
│ │ │ │ ├── extHostShare.ts
│ │ │ │ ├── extHostSpeech.ts
│ │ │ │ ├── extHostStatusBar.ts
│ │ │ │ ├── extHostStorage.ts
│ │ │ │ ├── extHostStoragePaths.ts
│ │ │ │ ├── extHostTask.ts
│ │ │ │ ├── extHostTelemetry.ts
│ │ │ │ ├── extHostTerminalService.ts
│ │ │ │ ├── extHostTerminalShellIntegration.ts
│ │ │ │ ├── extHostTestItem.ts
│ │ │ │ ├── extHostTesting.ts
│ │ │ │ ├── extHostTestingPrivateApi.ts
│ │ │ │ ├── extHostTextEditor.ts
│ │ │ │ ├── extHostTextEditors.ts
│ │ │ │ ├── extHostTheming.ts
│ │ │ │ ├── extHostTimeline.ts
│ │ │ │ ├── extHostTreeViews.ts
│ │ │ │ ├── extHostTunnelService.ts
│ │ │ │ ├── extHostTypeConverters.ts
│ │ │ │ ├── extHostTypes.ts
│ │ │ │ ├── extHostUriOpener.ts
│ │ │ │ ├── extHostUriTransformerService.ts
│ │ │ │ ├── extHostUrls.ts
│ │ │ │ ├── extHostVariableResolverService.ts
│ │ │ │ ├── extHostWebview.ts
│ │ │ │ ├── extHostWebviewMessaging.ts
│ │ │ │ ├── extHostWebviewPanels.ts
│ │ │ │ ├── extHostWebviewView.ts
│ │ │ │ ├── extHostWindow.ts
│ │ │ │ ├── extHostWorkspace.ts
│ │ │ │ ├── extensionHostMain.ts
│ │ │ │ ├── jsonValidationExtensionPoint.ts
│ │ │ │ └── shared/
│ │ │ │ ├── dataTransferCache.ts
│ │ │ │ └── tasks.ts
│ │ │ ├── node/
│ │ │ │ ├── extHost.node.services.ts
│ │ │ │ ├── extHostCLIServer.ts
│ │ │ │ ├── extHostConsoleForwarder.ts
│ │ │ │ ├── extHostDebugService.ts
│ │ │ │ ├── extHostDiskFileSystemProvider.ts
│ │ │ │ ├── extHostDownloadService.ts
│ │ │ │ ├── extHostExtensionService.ts
│ │ │ │ ├── extHostLoggerService.ts
│ │ │ │ ├── extHostMpcNode.ts
│ │ │ │ ├── extHostSearch.ts
│ │ │ │ ├── extHostStoragePaths.ts
│ │ │ │ ├── extHostTask.ts
│ │ │ │ ├── extHostTerminalService.ts
│ │ │ │ ├── extHostTunnelService.ts
│ │ │ │ ├── extHostVariableResolverService.ts
│ │ │ │ ├── extensionHostProcess.ts
│ │ │ │ ├── proxyResolver.ts
│ │ │ │ └── uriTransformer.ts
│ │ │ ├── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── extHost.api.impl.test.ts
│ │ │ │ │ ├── extHostApiCommands.test.ts
│ │ │ │ │ ├── extHostAuthentication.integrationTest.ts
│ │ │ │ │ ├── extHostBulkEdits.test.ts
│ │ │ │ │ ├── extHostCommands.test.ts
│ │ │ │ │ ├── extHostConfiguration.test.ts
│ │ │ │ │ ├── extHostDecorations.test.ts
│ │ │ │ │ ├── extHostDiagnostics.test.ts
│ │ │ │ │ ├── extHostDocumentContentProvider.test.ts
│ │ │ │ │ ├── extHostDocumentData.test.perf-data.ts
│ │ │ │ │ ├── extHostDocumentData.test.ts
│ │ │ │ │ ├── extHostDocumentSaveParticipant.test.ts
│ │ │ │ │ ├── extHostDocumentsAndEditors.test.ts
│ │ │ │ │ ├── extHostEditorTabs.test.ts
│ │ │ │ │ ├── extHostFileSystemEventService.test.ts
│ │ │ │ │ ├── extHostLanguageFeatures.test.ts
│ │ │ │ │ ├── extHostMessagerService.test.ts
│ │ │ │ │ ├── extHostNotebook.test.ts
│ │ │ │ │ ├── extHostNotebookKernel.test.ts
│ │ │ │ │ ├── extHostTelemetry.test.ts
│ │ │ │ │ ├── extHostTesting.test.ts
│ │ │ │ │ ├── extHostTextEditor.test.ts
│ │ │ │ │ ├── extHostTreeViews.test.ts
│ │ │ │ │ ├── extHostTypeConverter.test.ts
│ │ │ │ │ ├── extHostTypes.test.ts
│ │ │ │ │ ├── extHostWebview.test.ts
│ │ │ │ │ ├── extHostWorkspace.test.ts
│ │ │ │ │ ├── mainThreadBulkEdits.test.ts
│ │ │ │ │ ├── mainThreadCommands.test.ts
│ │ │ │ │ ├── mainThreadConfiguration.test.ts
│ │ │ │ │ ├── mainThreadDiagnostics.test.ts
│ │ │ │ │ ├── mainThreadDocumentContentProviders.test.ts
│ │ │ │ │ ├── mainThreadDocuments.test.ts
│ │ │ │ │ ├── mainThreadDocumentsAndEditors.test.ts
│ │ │ │ │ ├── mainThreadEditors.test.ts
│ │ │ │ │ ├── mainThreadManagedSockets.test.ts
│ │ │ │ │ ├── mainThreadTreeViews.test.ts
│ │ │ │ │ └── mainThreadWorkspace.test.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── extHostExtensionActivator.test.ts
│ │ │ │ │ ├── extHostTerminalShellIntegration.test.ts
│ │ │ │ │ ├── extensionHostMain.test.ts
│ │ │ │ │ └── testRPCProtocol.ts
│ │ │ │ └── node/
│ │ │ │ ├── extHostSearch.test.ts
│ │ │ │ └── extHostTunnelService.test.ts
│ │ │ └── worker/
│ │ │ ├── extHost.worker.services.ts
│ │ │ ├── extHostConsoleForwarder.ts
│ │ │ ├── extHostExtensionService.ts
│ │ │ ├── extensionHostWorker.ts
│ │ │ └── extensionHostWorkerMain.ts
│ │ ├── browser/
│ │ │ ├── actions/
│ │ │ │ ├── developerActions.ts
│ │ │ │ ├── helpActions.ts
│ │ │ │ ├── layoutActions.ts
│ │ │ │ ├── listCommands.ts
│ │ │ │ ├── media/
│ │ │ │ │ └── actions.css
│ │ │ │ ├── navigationActions.ts
│ │ │ │ ├── quickAccessActions.ts
│ │ │ │ ├── textInputActions.ts
│ │ │ │ ├── widgetNavigationCommands.ts
│ │ │ │ ├── windowActions.ts
│ │ │ │ ├── workspaceActions.ts
│ │ │ │ └── workspaceCommands.ts
│ │ │ ├── actions.ts
│ │ │ ├── codeeditor.ts
│ │ │ ├── composite.ts
│ │ │ ├── contextkeys.ts
│ │ │ ├── dnd.ts
│ │ │ ├── editor.ts
│ │ │ ├── labels.ts
│ │ │ ├── layout.ts
│ │ │ ├── media/
│ │ │ │ ├── part.css
│ │ │ │ └── style.css
│ │ │ ├── panecomposite.ts
│ │ │ ├── part.ts
│ │ │ ├── parts/
│ │ │ │ ├── activitybar/
│ │ │ │ │ ├── activitybarPart.ts
│ │ │ │ │ └── media/
│ │ │ │ │ ├── activityaction.css
│ │ │ │ │ └── activitybarpart.css
│ │ │ │ ├── auxiliarybar/
│ │ │ │ │ ├── auxiliaryBarActions.ts
│ │ │ │ │ ├── auxiliaryBarPart.ts
│ │ │ │ │ └── media/
│ │ │ │ │ └── auxiliaryBarPart.css
│ │ │ │ ├── banner/
│ │ │ │ │ ├── bannerPart.ts
│ │ │ │ │ └── media/
│ │ │ │ │ └── bannerpart.css
│ │ │ │ ├── compositeBar.ts
│ │ │ │ ├── compositeBarActions.ts
│ │ │ │ ├── compositePart.ts
│ │ │ │ ├── dialogs/
│ │ │ │ │ ├── dialog.web.contribution.ts
│ │ │ │ │ └── dialogHandler.ts
│ │ │ │ ├── editor/
│ │ │ │ │ ├── auxiliaryEditorPart.ts
│ │ │ │ │ ├── binaryDiffEditor.ts
│ │ │ │ │ ├── binaryEditor.ts
│ │ │ │ │ ├── breadcrumbs.ts
│ │ │ │ │ ├── breadcrumbsControl.ts
│ │ │ │ │ ├── breadcrumbsModel.ts
│ │ │ │ │ ├── breadcrumbsPicker.ts
│ │ │ │ │ ├── diffEditorCommands.ts
│ │ │ │ │ ├── editor.contribution.ts
│ │ │ │ │ ├── editor.ts
│ │ │ │ │ ├── editorActions.ts
│ │ │ │ │ ├── editorAutoSave.ts
│ │ │ │ │ ├── editorCommands.ts
│ │ │ │ │ ├── editorCommandsContext.ts
│ │ │ │ │ ├── editorConfiguration.ts
│ │ │ │ │ ├── editorDropTarget.ts
│ │ │ │ │ ├── editorGroupView.ts
│ │ │ │ │ ├── editorGroupWatermark.ts
│ │ │ │ │ ├── editorPane.ts
│ │ │ │ │ ├── editorPanes.ts
│ │ │ │ │ ├── editorPart.ts
│ │ │ │ │ ├── editorParts.ts
│ │ │ │ │ ├── editorPlaceholder.ts
│ │ │ │ │ ├── editorQuickAccess.ts
│ │ │ │ │ ├── editorStatus.ts
│ │ │ │ │ ├── editorTabsControl.ts
│ │ │ │ │ ├── editorTitleControl.ts
│ │ │ │ │ ├── editorWithViewState.ts
│ │ │ │ │ ├── editorsObserver.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── breadcrumbscontrol.css
│ │ │ │ │ │ ├── editordroptarget.css
│ │ │ │ │ │ ├── editorgroupview.css
│ │ │ │ │ │ ├── editorplaceholder.css
│ │ │ │ │ │ ├── editorquickaccess.css
│ │ │ │ │ │ ├── editorstatus.css
│ │ │ │ │ │ ├── editortabscontrol.css
│ │ │ │ │ │ ├── editortitlecontrol.css
│ │ │ │ │ │ ├── multieditortabscontrol.css
│ │ │ │ │ │ ├── sidebysideeditor.css
│ │ │ │ │ │ └── singleeditortabscontrol.css
│ │ │ │ │ ├── multiEditorTabsControl.ts
│ │ │ │ │ ├── multiRowEditorTabsControl.ts
│ │ │ │ │ ├── noEditorTabsControl.ts
│ │ │ │ │ ├── sideBySideEditor.ts
│ │ │ │ │ ├── singleEditorTabsControl.ts
│ │ │ │ │ ├── textCodeEditor.ts
│ │ │ │ │ ├── textDiffEditor.ts
│ │ │ │ │ ├── textEditor.ts
│ │ │ │ │ └── textResourceEditor.ts
│ │ │ │ ├── globalCompositeBar.ts
│ │ │ │ ├── media/
│ │ │ │ │ ├── compositepart.css
│ │ │ │ │ └── paneCompositePart.css
│ │ │ │ ├── notifications/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── notificationsActions.css
│ │ │ │ │ │ ├── notificationsCenter.css
│ │ │ │ │ │ ├── notificationsList.css
│ │ │ │ │ │ └── notificationsToasts.css
│ │ │ │ │ ├── notificationAccessibleView.ts
│ │ │ │ │ ├── notificationsActions.ts
│ │ │ │ │ ├── notificationsAlerts.ts
│ │ │ │ │ ├── notificationsCenter.ts
│ │ │ │ │ ├── notificationsCommands.ts
│ │ │ │ │ ├── notificationsList.ts
│ │ │ │ │ ├── notificationsStatus.ts
│ │ │ │ │ ├── notificationsToasts.ts
│ │ │ │ │ └── notificationsViewer.ts
│ │ │ │ ├── paneCompositeBar.ts
│ │ │ │ ├── paneCompositePart.ts
│ │ │ │ ├── paneCompositePartService.ts
│ │ │ │ ├── panel/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── panelpart.css
│ │ │ │ │ ├── panelActions.ts
│ │ │ │ │ └── panelPart.ts
│ │ │ │ ├── sidebar/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── sidebarpart.css
│ │ │ │ │ ├── sidebarActions.ts
│ │ │ │ │ └── sidebarPart.ts
│ │ │ │ ├── statusbar/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── statusbarpart.css
│ │ │ │ │ ├── statusbarActions.ts
│ │ │ │ │ ├── statusbarItem.ts
│ │ │ │ │ ├── statusbarModel.ts
│ │ │ │ │ └── statusbarPart.ts
│ │ │ │ ├── titlebar/
│ │ │ │ │ ├── commandCenterControl.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── menubarControl.css
│ │ │ │ │ │ └── titlebarpart.css
│ │ │ │ │ ├── menubarControl.ts
│ │ │ │ │ ├── titlebarActions.ts
│ │ │ │ │ ├── titlebarPart.ts
│ │ │ │ │ └── windowTitle.ts
│ │ │ │ └── views/
│ │ │ │ ├── checkbox.ts
│ │ │ │ ├── media/
│ │ │ │ │ ├── paneviewlet.css
│ │ │ │ │ └── views.css
│ │ │ │ ├── treeView.ts
│ │ │ │ ├── viewFilter.ts
│ │ │ │ ├── viewPane.ts
│ │ │ │ ├── viewPaneContainer.ts
│ │ │ │ └── viewsViewlet.ts
│ │ │ ├── quickaccess.ts
│ │ │ ├── style.ts
│ │ │ ├── web.api.ts
│ │ │ ├── web.factory.ts
│ │ │ ├── web.main.ts
│ │ │ ├── window.ts
│ │ │ ├── workbench.contribution.ts
│ │ │ └── workbench.ts
│ │ ├── common/
│ │ │ ├── activity.ts
│ │ │ ├── comments.ts
│ │ │ ├── component.ts
│ │ │ ├── composite.ts
│ │ │ ├── configuration.ts
│ │ │ ├── contextkeys.ts
│ │ │ ├── contributions.ts
│ │ │ ├── dialogs.ts
│ │ │ ├── editor/
│ │ │ │ ├── binaryEditorModel.ts
│ │ │ │ ├── diffEditorInput.ts
│ │ │ │ ├── diffEditorModel.ts
│ │ │ │ ├── editorGroupModel.ts
│ │ │ │ ├── editorInput.ts
│ │ │ │ ├── editorModel.ts
│ │ │ │ ├── editorOptions.ts
│ │ │ │ ├── filteredEditorGroupModel.ts
│ │ │ │ ├── resourceEditorInput.ts
│ │ │ │ ├── sideBySideEditorInput.ts
│ │ │ │ ├── textDiffEditorModel.ts
│ │ │ │ ├── textEditorModel.ts
│ │ │ │ ├── textResourceEditorInput.ts
│ │ │ │ └── textResourceEditorModel.ts
│ │ │ ├── editor.ts
│ │ │ ├── memento.ts
│ │ │ ├── notifications.ts
│ │ │ ├── panecomposite.ts
│ │ │ ├── resources.ts
│ │ │ ├── theme.ts
│ │ │ └── views.ts
│ │ ├── contrib/
│ │ │ ├── accessibility/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── accessibility.contribution.ts
│ │ │ │ │ ├── accessibilityConfiguration.ts
│ │ │ │ │ ├── accessibilityStatus.ts
│ │ │ │ │ ├── accessibleView.ts
│ │ │ │ │ ├── accessibleViewActions.ts
│ │ │ │ │ ├── accessibleViewContributions.ts
│ │ │ │ │ ├── accessibleViewKeybindingResolver.ts
│ │ │ │ │ ├── editorAccessibilityHelp.ts
│ │ │ │ │ ├── extensionAccesibilityHelp.contribution.ts
│ │ │ │ │ └── unfocusedViewDimmingContribution.ts
│ │ │ │ └── common/
│ │ │ │ └── accessibilityCommands.ts
│ │ │ ├── accessibilitySignals/
│ │ │ │ └── browser/
│ │ │ │ ├── accessibilitySignal.contribution.ts
│ │ │ │ ├── accessibilitySignalDebuggerContribution.ts
│ │ │ │ ├── commands.ts
│ │ │ │ ├── editorTextPropertySignalsContribution.ts
│ │ │ │ ├── openDiffEditorAnnouncement.ts
│ │ │ │ └── saveAccessibilitySignal.ts
│ │ │ ├── authentication/
│ │ │ │ └── browser/
│ │ │ │ ├── actions/
│ │ │ │ │ ├── manageAccountPreferencesForExtensionAction.ts
│ │ │ │ │ ├── manageTrustedExtensionsForAccountAction.ts
│ │ │ │ │ └── signOutOfAccountAction.ts
│ │ │ │ └── authentication.contribution.ts
│ │ │ ├── bracketPairColorizer2Telemetry/
│ │ │ │ └── browser/
│ │ │ │ └── bracketPairColorizer2Telemetry.contribution.ts
│ │ │ ├── bulkEdit/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── bulkCellEdits.ts
│ │ │ │ │ ├── bulkEditService.ts
│ │ │ │ │ ├── bulkFileEdits.ts
│ │ │ │ │ ├── bulkTextEdits.ts
│ │ │ │ │ ├── conflicts.ts
│ │ │ │ │ ├── opaqueEdits.ts
│ │ │ │ │ └── preview/
│ │ │ │ │ ├── bulkEdit.contribution.ts
│ │ │ │ │ ├── bulkEdit.css
│ │ │ │ │ ├── bulkEditPane.ts
│ │ │ │ │ ├── bulkEditPreview.ts
│ │ │ │ │ └── bulkEditTree.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── bulkCellEdits.test.ts
│ │ │ │ └── bulkEditPreview.test.ts
│ │ │ ├── callHierarchy/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── callHierarchy.contribution.ts
│ │ │ │ │ ├── callHierarchyPeek.ts
│ │ │ │ │ ├── callHierarchyTree.ts
│ │ │ │ │ └── media/
│ │ │ │ │ └── callHierarchy.css
│ │ │ │ └── common/
│ │ │ │ └── callHierarchy.ts
│ │ │ ├── chat/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── actions/
│ │ │ │ │ │ ├── chatAccessibilityHelp.ts
│ │ │ │ │ │ ├── chatActions.ts
│ │ │ │ │ │ ├── chatAttachPromptAction/
│ │ │ │ │ │ │ ├── chatAttachPromptAction.ts
│ │ │ │ │ │ │ └── dialogs/
│ │ │ │ │ │ │ └── askToSelectPrompt/
│ │ │ │ │ │ │ ├── askToSelectPrompt.ts
│ │ │ │ │ │ │ ├── constants.ts
│ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ ├── attachPrompts.ts
│ │ │ │ │ │ │ ├── createPlaceholderText.ts
│ │ │ │ │ │ │ ├── createPromptPickItem.ts
│ │ │ │ │ │ │ └── handleButtonClick.ts
│ │ │ │ │ │ ├── chatClear.ts
│ │ │ │ │ │ ├── chatClearActions.ts
│ │ │ │ │ │ ├── chatCodeblockActions.ts
│ │ │ │ │ │ ├── chatContextActions.ts
│ │ │ │ │ │ ├── chatCopyActions.ts
│ │ │ │ │ │ ├── chatDeveloperActions.ts
│ │ │ │ │ │ ├── chatExecuteActions.ts
│ │ │ │ │ │ ├── chatFileTreeActions.ts
│ │ │ │ │ │ ├── chatGettingStarted.ts
│ │ │ │ │ │ ├── chatImportExport.ts
│ │ │ │ │ │ ├── chatMoveActions.ts
│ │ │ │ │ │ ├── chatQuickInputActions.ts
│ │ │ │ │ │ ├── chatTitleActions.ts
│ │ │ │ │ │ ├── chatToolActions.ts
│ │ │ │ │ │ ├── chatTransfer.ts
│ │ │ │ │ │ └── codeBlockOperations.ts
│ │ │ │ │ ├── attachments/
│ │ │ │ │ │ ├── implicitContextAttachment.ts
│ │ │ │ │ │ └── promptAttachments/
│ │ │ │ │ │ ├── promptAttachmentWidget.ts
│ │ │ │ │ │ └── promptAttachmentsCollectionWidget.ts
│ │ │ │ │ ├── chat.contribution.ts
│ │ │ │ │ ├── chat.ts
│ │ │ │ │ ├── chatAccessibilityProvider.ts
│ │ │ │ │ ├── chatAccessibilityService.ts
│ │ │ │ │ ├── chatAgentHover.ts
│ │ │ │ │ ├── chatAttachmentModel/
│ │ │ │ │ │ ├── chatPromptAttachmentModel.ts
│ │ │ │ │ │ └── chatPromptAttachmentsCollection.ts
│ │ │ │ │ ├── chatAttachmentModel.ts
│ │ │ │ │ ├── chatAttachmentWidgets.ts
│ │ │ │ │ ├── chatContentParts/
│ │ │ │ │ │ ├── chatAgentCommandContentPart.ts
│ │ │ │ │ │ ├── chatAttachmentsContentPart.ts
│ │ │ │ │ │ ├── chatCodeCitationContentPart.ts
│ │ │ │ │ │ ├── chatCollapsibleContentPart.ts
│ │ │ │ │ │ ├── chatCollections.ts
│ │ │ │ │ │ ├── chatCommandContentPart.ts
│ │ │ │ │ │ ├── chatConfirmationContentPart.ts
│ │ │ │ │ │ ├── chatConfirmationWidget.ts
│ │ │ │ │ │ ├── chatContentParts.ts
│ │ │ │ │ │ ├── chatMarkdownAnchorService.ts
│ │ │ │ │ │ ├── chatMarkdownContentPart.ts
│ │ │ │ │ │ ├── chatProgressContentPart.ts
│ │ │ │ │ │ ├── chatQuotaExceededPart.ts
│ │ │ │ │ │ ├── chatReferencesContentPart.ts
│ │ │ │ │ │ ├── chatTaskContentPart.ts
│ │ │ │ │ │ ├── chatTextEditContentPart.ts
│ │ │ │ │ │ ├── chatToolInvocationPart.ts
│ │ │ │ │ │ ├── chatTreeContentPart.ts
│ │ │ │ │ │ ├── chatWarningContentPart.ts
│ │ │ │ │ │ └── media/
│ │ │ │ │ │ └── chatConfirmationWidget.css
│ │ │ │ │ ├── chatDragAndDrop.ts
│ │ │ │ │ ├── chatEdinputInputContentProvider.ts
│ │ │ │ │ ├── chatEditing/
│ │ │ │ │ │ ├── chatEditing.ts
│ │ │ │ │ │ ├── chatEditingActions.ts
│ │ │ │ │ │ ├── chatEditingCodeEditorIntegration.ts
│ │ │ │ │ │ ├── chatEditingEditorAccessibility.ts
│ │ │ │ │ │ ├── chatEditingEditorActions.ts
│ │ │ │ │ │ ├── chatEditingEditorContextKeys.ts
│ │ │ │ │ │ ├── chatEditingEditorOverlay.ts
│ │ │ │ │ │ ├── chatEditingModifiedDocumentEntry.ts
│ │ │ │ │ │ ├── chatEditingModifiedFileEntry.ts
│ │ │ │ │ │ ├── chatEditingModifiedNotebookEntry.ts
│ │ │ │ │ │ ├── chatEditingServiceImpl.ts
│ │ │ │ │ │ ├── chatEditingSession.ts
│ │ │ │ │ │ ├── chatEditingTextModelContentProviders.ts
│ │ │ │ │ │ └── notebook/
│ │ │ │ │ │ ├── chatEditingModifiedNotebookDiff.ts
│ │ │ │ │ │ ├── chatEditingModifiedNotebookSnapshot.ts
│ │ │ │ │ │ ├── chatEditingNewNotebookContentEdits.ts
│ │ │ │ │ │ ├── chatEditingNotebookCellEntry.ts
│ │ │ │ │ │ ├── chatEditingNotebookEditorIntegration.ts
│ │ │ │ │ │ ├── chatEditingNotebookFileSystemProvider.ts
│ │ │ │ │ │ ├── helpers.ts
│ │ │ │ │ │ └── notebookCellChanges.ts
│ │ │ │ │ ├── chatEditor.ts
│ │ │ │ │ ├── chatEditorInput.ts
│ │ │ │ │ ├── chatFollowups.ts
│ │ │ │ │ ├── chatInlineAnchorWidget.ts
│ │ │ │ │ ├── chatInputPart.ts
│ │ │ │ │ ├── chatListRenderer.ts
│ │ │ │ │ ├── chatMarkdownDecorationsRenderer.ts
│ │ │ │ │ ├── chatMarkdownRenderer.ts
│ │ │ │ │ ├── chatOptions.ts
│ │ │ │ │ ├── chatParticipant.contribution.ts
│ │ │ │ │ ├── chatPasteProviders.ts
│ │ │ │ │ ├── chatQuick.ts
│ │ │ │ │ ├── chatResponseAccessibleView.ts
│ │ │ │ │ ├── chatSelectedTools.ts
│ │ │ │ │ ├── chatSetup.ts
│ │ │ │ │ ├── chatStatus.ts
│ │ │ │ │ ├── chatStatusItemService.ts
│ │ │ │ │ ├── chatVariables.ts
│ │ │ │ │ ├── chatViewPane.ts
│ │ │ │ │ ├── chatWidget.ts
│ │ │ │ │ ├── codeBlockContextProviderService.ts
│ │ │ │ │ ├── codeBlockPart.css
│ │ │ │ │ ├── codeBlockPart.ts
│ │ │ │ │ ├── contrib/
│ │ │ │ │ │ ├── chatDynamicVariables/
│ │ │ │ │ │ │ └── chatFileReference.ts
│ │ │ │ │ │ ├── chatDynamicVariables.ts
│ │ │ │ │ │ ├── chatImplicitContext.ts
│ │ │ │ │ │ ├── chatInputCompletions.ts
│ │ │ │ │ │ ├── chatInputEditorContrib.ts
│ │ │ │ │ │ ├── chatInputEditorHover.ts
│ │ │ │ │ │ ├── chatInputRelatedFilesContrib.ts
│ │ │ │ │ │ ├── editorHoverWrapper.ts
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── editorHoverWrapper.css
│ │ │ │ │ │ └── screenshot.ts
│ │ │ │ │ ├── imageUtils.ts
│ │ │ │ │ ├── languageModelToolsService.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── chat.css
│ │ │ │ │ │ ├── chatAgentHover.css
│ │ │ │ │ │ ├── chatCodeBlockPill.css
│ │ │ │ │ │ ├── chatEditingEditorOverlay.css
│ │ │ │ │ │ ├── chatEditorController.css
│ │ │ │ │ │ ├── chatEditorOverlay.css
│ │ │ │ │ │ ├── chatInlineAnchorWidget.css
│ │ │ │ │ │ ├── chatSetup.css
│ │ │ │ │ │ ├── chatStatus.css
│ │ │ │ │ │ ├── chatViewSetup.css
│ │ │ │ │ │ └── chatViewWelcome.css
│ │ │ │ │ ├── promptSyntax/
│ │ │ │ │ │ └── contributions/
│ │ │ │ │ │ ├── createPromptCommand/
│ │ │ │ │ │ │ ├── createPromptCommand.ts
│ │ │ │ │ │ │ ├── dialogs/
│ │ │ │ │ │ │ │ ├── askForPromptName.ts
│ │ │ │ │ │ │ │ └── askForPromptSourceFolder.ts
│ │ │ │ │ │ │ ├── errors.ts
│ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ └── createPromptFile.ts
│ │ │ │ │ │ └── usePromptCommand.ts
│ │ │ │ │ └── viewsWelcome/
│ │ │ │ │ ├── chatViewWelcomeController.ts
│ │ │ │ │ ├── chatViewsWelcome.ts
│ │ │ │ │ └── chatViewsWelcomeHandler.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── annotations.ts
│ │ │ │ │ ├── chat.ts
│ │ │ │ │ ├── chatActions.ts
│ │ │ │ │ ├── chatAgents.ts
│ │ │ │ │ ├── chatCodeMapperService.ts
│ │ │ │ │ ├── chatColors.ts
│ │ │ │ │ ├── chatContextKeys.ts
│ │ │ │ │ ├── chatEditingService.ts
│ │ │ │ │ ├── chatEntitlementService.ts
│ │ │ │ │ ├── chatModel.ts
│ │ │ │ │ ├── chatParserTypes.ts
│ │ │ │ │ ├── chatParticipantContribTypes.ts
│ │ │ │ │ ├── chatProgressTypes/
│ │ │ │ │ │ └── chatToolInvocation.ts
│ │ │ │ │ ├── chatRequestParser.ts
│ │ │ │ │ ├── chatService.ts
│ │ │ │ │ ├── chatServiceImpl.ts
│ │ │ │ │ ├── chatServiceTelemetry.ts
│ │ │ │ │ ├── chatSessionStore.ts
│ │ │ │ │ ├── chatSlashCommands.ts
│ │ │ │ │ ├── chatTransferService.ts
│ │ │ │ │ ├── chatVariables.ts
│ │ │ │ │ ├── chatViewModel.ts
│ │ │ │ │ ├── chatWidgetHistoryService.ts
│ │ │ │ │ ├── chatWordCounter.ts
│ │ │ │ │ ├── codeBlockModelCollection.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── ignoredFiles.ts
│ │ │ │ │ ├── languageModelStats.ts
│ │ │ │ │ ├── languageModelToolsService.ts
│ │ │ │ │ ├── languageModels.ts
│ │ │ │ │ ├── promptFileReferenceErrors.ts
│ │ │ │ │ ├── promptSyntax/
│ │ │ │ │ │ ├── codecs/
│ │ │ │ │ │ │ ├── chatPromptCodec.ts
│ │ │ │ │ │ │ ├── chatPromptDecoder.ts
│ │ │ │ │ │ │ ├── parsers/
│ │ │ │ │ │ │ │ └── promptVariableParser.ts
│ │ │ │ │ │ │ └── tokens/
│ │ │ │ │ │ │ ├── fileReference.ts
│ │ │ │ │ │ │ ├── promptToken.ts
│ │ │ │ │ │ │ └── promptVariable.ts
│ │ │ │ │ │ ├── constants.ts
│ │ │ │ │ │ ├── contentProviders/
│ │ │ │ │ │ │ ├── filePromptContentsProvider.ts
│ │ │ │ │ │ │ ├── promptContentsProviderBase.ts
│ │ │ │ │ │ │ ├── textModelContentsProvider.ts
│ │ │ │ │ │ │ └── types.d.ts
│ │ │ │ │ │ ├── languageFeatures/
│ │ │ │ │ │ │ ├── promptLinkDiagnosticsProvider.ts
│ │ │ │ │ │ │ ├── promptLinkProvider.ts
│ │ │ │ │ │ │ ├── promptPathAutocompletion.ts
│ │ │ │ │ │ │ └── types.d.ts
│ │ │ │ │ │ ├── parsers/
│ │ │ │ │ │ │ ├── basePromptParser.ts
│ │ │ │ │ │ │ ├── filePromptParser.ts
│ │ │ │ │ │ │ ├── textModelPromptParser.ts
│ │ │ │ │ │ │ ├── topError.ts
│ │ │ │ │ │ │ └── types.d.ts
│ │ │ │ │ │ ├── service/
│ │ │ │ │ │ │ ├── promptsService.ts
│ │ │ │ │ │ │ └── types.ts
│ │ │ │ │ │ └── utils/
│ │ │ │ │ │ └── promptFilesLocator.ts
│ │ │ │ │ ├── tools/
│ │ │ │ │ │ ├── editFileTool.ts
│ │ │ │ │ │ ├── insertNotebookCellsTool.ts
│ │ │ │ │ │ ├── languageModelToolsContribution.ts
│ │ │ │ │ │ ├── languageModelToolsParametersSchema.ts
│ │ │ │ │ │ ├── promptTsxTypes.ts
│ │ │ │ │ │ └── tools.ts
│ │ │ │ │ └── voiceChatService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── actions/
│ │ │ │ │ │ ├── chatDeveloperActions.ts
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── voiceChatActions.css
│ │ │ │ │ │ └── voiceChatActions.ts
│ │ │ │ │ ├── chat.contribution.ts
│ │ │ │ │ └── tools/
│ │ │ │ │ └── fetchPageTool.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── ChatMarkdownRenderer_CDATA.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_html_comments.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_invalid_HTML.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_invalid_HTML_with_attributes.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_mixed_valid_and_invalid_HTML.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_remote_images.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_self-closing_elements.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_simple.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_supportHtml_with_one-line_markdown.0.snap
│ │ │ │ │ │ ├── ChatMarkdownRenderer_supportHtml_with_one-line_markdown.1.snap
│ │ │ │ │ │ └── ChatMarkdownRenderer_valid_HTML.0.snap
│ │ │ │ │ ├── chatEditingModifiedNotebookEntry.test.ts
│ │ │ │ │ ├── chatEditingService.test.ts
│ │ │ │ │ ├── chatMarkdownRenderer.test.ts
│ │ │ │ │ ├── languageModelToolsService.test.ts
│ │ │ │ │ └── mockChatWidget.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── Annotations_extractVulnerabilitiesFromText_multiline.0.snap
│ │ │ │ │ │ ├── Annotations_extractVulnerabilitiesFromText_multiline.1.snap
│ │ │ │ │ │ ├── Annotations_extractVulnerabilitiesFromText_multiple_vulns.0.snap
│ │ │ │ │ │ ├── Annotations_extractVulnerabilitiesFromText_multiple_vulns.1.snap
│ │ │ │ │ │ ├── Annotations_extractVulnerabilitiesFromText_single_line.0.snap
│ │ │ │ │ │ ├── Annotations_extractVulnerabilitiesFromText_single_line.1.snap
│ │ │ │ │ │ ├── ChatRequestParser_agent_and_subcommand_after_newline.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agent_and_subcommand_with_leading_whitespace.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agent_but_edit_mode.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agent_not_first.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agent_with_question_mark.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agent_with_subcommand_after_text.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agents__subCommand.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agents_and_tools_and_multiline.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_agents_and_tools_and_multiline__part2.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_invalid_slash_command.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_multiple_slash_commands.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_plain_text.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_plain_text_with_newlines.0.snap
│ │ │ │ │ │ ├── ChatRequestParser_slash_command.0.snap
│ │ │ │ │ │ ├── ChatService_can_deserialize.0.snap
│ │ │ │ │ │ ├── ChatService_can_deserialize_with_response.0.snap
│ │ │ │ │ │ ├── ChatService_can_serialize.0.snap
│ │ │ │ │ │ ├── ChatService_can_serialize.1.snap
│ │ │ │ │ │ ├── ChatService_sendRequest_fails.0.snap
│ │ │ │ │ │ ├── Response_async_content.0.snap
│ │ │ │ │ │ ├── Response_async_content.1.snap
│ │ │ │ │ │ ├── Response_content__markdown.0.snap
│ │ │ │ │ │ ├── Response_inline_reference.0.snap
│ │ │ │ │ │ ├── Response_markdown__content.0.snap
│ │ │ │ │ │ ├── Response_markdown__markdown.0.snap
│ │ │ │ │ │ ├── Response_mergeable_markdown.0.snap
│ │ │ │ │ │ └── Response_not_mergeable_markdown.0.snap
│ │ │ │ │ ├── annotations.test.ts
│ │ │ │ │ ├── chatAgents.test.ts
│ │ │ │ │ ├── chatModel.test.ts
│ │ │ │ │ ├── chatRequestParser.test.ts
│ │ │ │ │ ├── chatService.test.ts
│ │ │ │ │ ├── chatWordCounter.test.ts
│ │ │ │ │ ├── languageModels.test.ts
│ │ │ │ │ ├── mockChatService.ts
│ │ │ │ │ ├── mockChatVariables.ts
│ │ │ │ │ ├── mockLanguageModelToolsService.ts
│ │ │ │ │ ├── promptSyntax/
│ │ │ │ │ │ ├── codecs/
│ │ │ │ │ │ │ ├── chatPromptCodec.test.ts
│ │ │ │ │ │ │ ├── chatPromptDecoder.test.ts
│ │ │ │ │ │ │ └── tokens/
│ │ │ │ │ │ │ ├── fileReference.test.ts
│ │ │ │ │ │ │ └── markdownLink.test.ts
│ │ │ │ │ │ ├── contentProviders/
│ │ │ │ │ │ │ └── filePromptContentsProvider.test.ts
│ │ │ │ │ │ ├── parsers/
│ │ │ │ │ │ │ └── textModelPromptParser.test.ts
│ │ │ │ │ │ ├── promptFileReference.test.ts
│ │ │ │ │ │ ├── service/
│ │ │ │ │ │ │ └── promptsService.test.ts
│ │ │ │ │ │ ├── testUtils/
│ │ │ │ │ │ │ ├── createUri.ts
│ │ │ │ │ │ │ ├── expectedReference.ts
│ │ │ │ │ │ │ ├── mockFilesystem.test.ts
│ │ │ │ │ │ │ └── mockFilesystem.ts
│ │ │ │ │ │ └── utils/
│ │ │ │ │ │ └── promptFilesLocator.test.ts
│ │ │ │ │ └── voiceChatService.test.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── voiceChatActions.test.ts
│ │ │ ├── codeActions/
│ │ │ │ └── browser/
│ │ │ │ ├── codeActions.contribution.ts
│ │ │ │ └── codeActionsContribution.ts
│ │ │ ├── codeEditor/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── accessibility/
│ │ │ │ │ │ ├── accessibility.css
│ │ │ │ │ │ └── accessibility.ts
│ │ │ │ │ ├── codeEditor.contribution.ts
│ │ │ │ │ ├── dictation/
│ │ │ │ │ │ ├── editorDictation.css
│ │ │ │ │ │ └── editorDictation.ts
│ │ │ │ │ ├── diffEditorAccessibilityHelp.ts
│ │ │ │ │ ├── diffEditorHelper.ts
│ │ │ │ │ ├── editorFeatures.ts
│ │ │ │ │ ├── editorLineNumberMenu.ts
│ │ │ │ │ ├── editorSettingsMigration.ts
│ │ │ │ │ ├── emptyTextEditorHint/
│ │ │ │ │ │ ├── emptyTextEditorHint.css
│ │ │ │ │ │ └── emptyTextEditorHint.ts
│ │ │ │ │ ├── find/
│ │ │ │ │ │ ├── simpleFindWidget.css
│ │ │ │ │ │ └── simpleFindWidget.ts
│ │ │ │ │ ├── inspectEditorTokens/
│ │ │ │ │ │ ├── inspectEditorTokens.css
│ │ │ │ │ │ └── inspectEditorTokens.ts
│ │ │ │ │ ├── inspectKeybindings.ts
│ │ │ │ │ ├── largeFileOptimizations.ts
│ │ │ │ │ ├── menuPreventer.ts
│ │ │ │ │ ├── outline/
│ │ │ │ │ │ ├── documentSymbolsOutline.ts
│ │ │ │ │ │ ├── documentSymbolsTree.css
│ │ │ │ │ │ └── documentSymbolsTree.ts
│ │ │ │ │ ├── quickaccess/
│ │ │ │ │ │ ├── gotoLineQuickAccess.ts
│ │ │ │ │ │ └── gotoSymbolQuickAccess.ts
│ │ │ │ │ ├── saveParticipants.ts
│ │ │ │ │ ├── selectionClipboard.ts
│ │ │ │ │ ├── simpleEditorOptions.ts
│ │ │ │ │ ├── suggestEnabledInput/
│ │ │ │ │ │ ├── suggestEnabledInput.css
│ │ │ │ │ │ └── suggestEnabledInput.ts
│ │ │ │ │ ├── toggleColumnSelection.ts
│ │ │ │ │ ├── toggleMinimap.ts
│ │ │ │ │ ├── toggleMultiCursorModifier.ts
│ │ │ │ │ ├── toggleOvertype.ts
│ │ │ │ │ ├── toggleRenderControlCharacter.ts
│ │ │ │ │ ├── toggleRenderWhitespace.ts
│ │ │ │ │ ├── toggleWordWrap.ts
│ │ │ │ │ ├── workbenchEditorWorkerService.ts
│ │ │ │ │ └── workbenchReferenceSearch.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── languageConfigurationExtensionPoint.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── codeEditor.contribution.ts
│ │ │ │ │ ├── displayChangeRemeasureFonts.ts
│ │ │ │ │ ├── inputClipboardActions.ts
│ │ │ │ │ ├── selectionClipboard.ts
│ │ │ │ │ ├── sleepResumeRepaintMinimap.ts
│ │ │ │ │ └── startDebugTextMate.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ └── saveParticipant.test.ts
│ │ │ │ └── node/
│ │ │ │ ├── autoindent.test.ts
│ │ │ │ └── language-configuration.json
│ │ │ ├── commands/
│ │ │ │ └── common/
│ │ │ │ └── commands.contribution.ts
│ │ │ ├── comments/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── commentColors.ts
│ │ │ │ │ ├── commentFormActions.ts
│ │ │ │ │ ├── commentGlyphWidget.ts
│ │ │ │ │ ├── commentMenus.ts
│ │ │ │ │ ├── commentNode.ts
│ │ │ │ │ ├── commentReply.ts
│ │ │ │ │ ├── commentService.ts
│ │ │ │ │ ├── commentThreadAdditionalActions.ts
│ │ │ │ │ ├── commentThreadBody.ts
│ │ │ │ │ ├── commentThreadHeader.ts
│ │ │ │ │ ├── commentThreadRangeDecorator.ts
│ │ │ │ │ ├── commentThreadWidget.ts
│ │ │ │ │ ├── commentThreadZoneWidget.ts
│ │ │ │ │ ├── comments.contribution.ts
│ │ │ │ │ ├── comments.ts
│ │ │ │ │ ├── commentsAccessibility.ts
│ │ │ │ │ ├── commentsAccessibleView.ts
│ │ │ │ │ ├── commentsController.ts
│ │ │ │ │ ├── commentsEditorContribution.ts
│ │ │ │ │ ├── commentsFilterOptions.ts
│ │ │ │ │ ├── commentsInputContentProvider.ts
│ │ │ │ │ ├── commentsModel.ts
│ │ │ │ │ ├── commentsTreeViewer.ts
│ │ │ │ │ ├── commentsView.ts
│ │ │ │ │ ├── commentsViewActions.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── panel.css
│ │ │ │ │ │ └── review.css
│ │ │ │ │ ├── reactionsAction.ts
│ │ │ │ │ ├── simpleCommentEditor.ts
│ │ │ │ │ └── timestamp.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── commentCommandIds.ts
│ │ │ │ │ ├── commentContextKeys.ts
│ │ │ │ │ ├── commentModel.ts
│ │ │ │ │ ├── commentThreadWidget.ts
│ │ │ │ │ └── commentsConfiguration.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── commentsView.test.ts
│ │ │ ├── contextmenu/
│ │ │ │ └── browser/
│ │ │ │ └── contextmenu.contribution.ts
│ │ │ ├── customEditor/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── customEditor.contribution.ts
│ │ │ │ │ ├── customEditorInput.ts
│ │ │ │ │ ├── customEditorInputFactory.ts
│ │ │ │ │ ├── customEditors.ts
│ │ │ │ │ └── media/
│ │ │ │ │ └── customEditor.css
│ │ │ │ └── common/
│ │ │ │ ├── contributedCustomEditors.ts
│ │ │ │ ├── customEditor.ts
│ │ │ │ ├── customEditorModelManager.ts
│ │ │ │ ├── customTextEditorModel.ts
│ │ │ │ └── extensionPoint.ts
│ │ │ ├── debug/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── baseDebugView.ts
│ │ │ │ │ ├── breakpointEditorContribution.ts
│ │ │ │ │ ├── breakpointWidget.ts
│ │ │ │ │ ├── breakpointsView.ts
│ │ │ │ │ ├── callStackEditorContribution.ts
│ │ │ │ │ ├── callStackView.ts
│ │ │ │ │ ├── callStackWidget.ts
│ │ │ │ │ ├── debug.contribution.ts
│ │ │ │ │ ├── debugANSIHandling.ts
│ │ │ │ │ ├── debugActionViewItems.ts
│ │ │ │ │ ├── debugAdapterManager.ts
│ │ │ │ │ ├── debugColors.ts
│ │ │ │ │ ├── debugCommands.ts
│ │ │ │ │ ├── debugConfigurationManager.ts
│ │ │ │ │ ├── debugConsoleQuickAccess.ts
│ │ │ │ │ ├── debugEditorActions.ts
│ │ │ │ │ ├── debugEditorContribution.ts
│ │ │ │ │ ├── debugExpressionRenderer.ts
│ │ │ │ │ ├── debugHover.ts
│ │ │ │ │ ├── debugIcons.ts
│ │ │ │ │ ├── debugMemory.ts
│ │ │ │ │ ├── debugProgress.ts
│ │ │ │ │ ├── debugQuickAccess.ts
│ │ │ │ │ ├── debugService.ts
│ │ │ │ │ ├── debugSession.ts
│ │ │ │ │ ├── debugSessionPicker.ts
│ │ │ │ │ ├── debugSettingMigration.ts
│ │ │ │ │ ├── debugStatus.ts
│ │ │ │ │ ├── debugTaskRunner.ts
│ │ │ │ │ ├── debugTitle.ts
│ │ │ │ │ ├── debugToolBar.ts
│ │ │ │ │ ├── debugViewlet.ts
│ │ │ │ │ ├── disassemblyView.ts
│ │ │ │ │ ├── exceptionWidget.ts
│ │ │ │ │ ├── extensionHostDebugService.ts
│ │ │ │ │ ├── linkDetector.ts
│ │ │ │ │ ├── loadedScriptsView.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── breakpointWidget.css
│ │ │ │ │ │ ├── callStackEditorContribution.css
│ │ │ │ │ │ ├── callStackWidget.css
│ │ │ │ │ │ ├── debug.contribution.css
│ │ │ │ │ │ ├── debugHover.css
│ │ │ │ │ │ ├── debugToolBar.css
│ │ │ │ │ │ ├── debugViewlet.css
│ │ │ │ │ │ ├── exceptionWidget.css
│ │ │ │ │ │ └── repl.css
│ │ │ │ │ ├── rawDebugSession.ts
│ │ │ │ │ ├── repl.ts
│ │ │ │ │ ├── replAccessibilityHelp.ts
│ │ │ │ │ ├── replAccessibleView.ts
│ │ │ │ │ ├── replFilter.ts
│ │ │ │ │ ├── replViewer.ts
│ │ │ │ │ ├── runAndDebugAccessibilityHelp.ts
│ │ │ │ │ ├── statusbarColorProvider.ts
│ │ │ │ │ ├── variablesView.ts
│ │ │ │ │ ├── watchExpressionsView.ts
│ │ │ │ │ └── welcomeView.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractDebugAdapter.ts
│ │ │ │ │ ├── breakpoints.ts
│ │ │ │ │ ├── debug.ts
│ │ │ │ │ ├── debugAccessibilityAnnouncer.ts
│ │ │ │ │ ├── debugCompoundRoot.ts
│ │ │ │ │ ├── debugContentProvider.ts
│ │ │ │ │ ├── debugContext.ts
│ │ │ │ │ ├── debugLifecycle.ts
│ │ │ │ │ ├── debugModel.ts
│ │ │ │ │ ├── debugProtocol.d.ts
│ │ │ │ │ ├── debugSchemas.ts
│ │ │ │ │ ├── debugSource.ts
│ │ │ │ │ ├── debugStorage.ts
│ │ │ │ │ ├── debugTelemetry.ts
│ │ │ │ │ ├── debugUtils.ts
│ │ │ │ │ ├── debugViewModel.ts
│ │ │ │ │ ├── debugVisualizers.ts
│ │ │ │ │ ├── debugger.ts
│ │ │ │ │ ├── disassemblyViewInput.ts
│ │ │ │ │ ├── loadedScriptsPicker.ts
│ │ │ │ │ ├── replAccessibilityAnnouncer.ts
│ │ │ │ │ └── replModel.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── extensionHostDebugService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── debugAdapter.ts
│ │ │ │ │ ├── telemetryApp.ts
│ │ │ │ │ └── terminals.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── baseDebugView.test.ts
│ │ │ │ │ ├── breakpoints.test.ts
│ │ │ │ │ ├── callStack.test.ts
│ │ │ │ │ ├── debugANSIHandling.test.ts
│ │ │ │ │ ├── debugConfigurationManager.test.ts
│ │ │ │ │ ├── debugHover.test.ts
│ │ │ │ │ ├── debugMemory.test.ts
│ │ │ │ │ ├── debugSession.test.ts
│ │ │ │ │ ├── debugSource.test.ts
│ │ │ │ │ ├── debugUtils.test.ts
│ │ │ │ │ ├── debugViewModel.test.ts
│ │ │ │ │ ├── linkDetector.test.ts
│ │ │ │ │ ├── mockDebugModel.ts
│ │ │ │ │ ├── rawDebugSession.test.ts
│ │ │ │ │ ├── repl.test.ts
│ │ │ │ │ ├── variablesView.test.ts
│ │ │ │ │ ├── watch.test.ts
│ │ │ │ │ └── watchExpressionView.test.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractDebugAdapter.test.ts
│ │ │ │ │ ├── debugModel.test.ts
│ │ │ │ │ └── mockDebug.ts
│ │ │ │ └── node/
│ │ │ │ ├── debugger.test.ts
│ │ │ │ ├── streamDebugAdapter.test.ts
│ │ │ │ └── terminals.test.ts
│ │ │ ├── deprecatedExtensionMigrator/
│ │ │ │ └── browser/
│ │ │ │ └── deprecatedExtensionMigrator.contribution.ts
│ │ │ ├── dropOrPasteInto/
│ │ │ │ └── browser/
│ │ │ │ ├── commands.ts
│ │ │ │ ├── configurationSchema.ts
│ │ │ │ └── dropOrPasteInto.contribution.ts
│ │ │ ├── editSessions/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── editSessions.contribution.ts
│ │ │ │ │ ├── editSessionsFileSystemProvider.ts
│ │ │ │ │ ├── editSessionsStorageService.ts
│ │ │ │ │ └── editSessionsViews.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── editSessions.ts
│ │ │ │ │ ├── editSessionsLogService.ts
│ │ │ │ │ ├── editSessionsStorageClient.ts
│ │ │ │ │ └── workspaceStateSync.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── editSessions.test.ts
│ │ │ ├── emergencyAlert/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── emergencyAlert.contribution.ts
│ │ │ ├── emmet/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── actions/
│ │ │ │ │ │ └── expandAbbreviation.ts
│ │ │ │ │ ├── emmet.contribution.ts
│ │ │ │ │ └── emmetActions.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── emmetAction.test.ts
│ │ │ ├── encryption/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── encryption.contribution.ts
│ │ │ ├── extensions/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── abstractRuntimeExtensionsEditor.ts
│ │ │ │ │ ├── browserRuntimeExtensionsEditor.ts
│ │ │ │ │ ├── configBasedRecommendations.ts
│ │ │ │ │ ├── exeBasedRecommendations.ts
│ │ │ │ │ ├── extensionEditor.ts
│ │ │ │ │ ├── extensionEnablementWorkspaceTrustTransitionParticipant.ts
│ │ │ │ │ ├── extensionFeaturesTab.ts
│ │ │ │ │ ├── extensionRecommendationNotificationService.ts
│ │ │ │ │ ├── extensionRecommendations.ts
│ │ │ │ │ ├── extensionRecommendationsService.ts
│ │ │ │ │ ├── extensions.contribution.ts
│ │ │ │ │ ├── extensions.web.contribution.ts
│ │ │ │ │ ├── extensionsActions.ts
│ │ │ │ │ ├── extensionsActivationProgress.ts
│ │ │ │ │ ├── extensionsCompletionItemsProvider.ts
│ │ │ │ │ ├── extensionsDependencyChecker.ts
│ │ │ │ │ ├── extensionsIcons.ts
│ │ │ │ │ ├── extensionsList.ts
│ │ │ │ │ ├── extensionsQuickAccess.ts
│ │ │ │ │ ├── extensionsViewer.ts
│ │ │ │ │ ├── extensionsViewlet.ts
│ │ │ │ │ ├── extensionsViews.ts
│ │ │ │ │ ├── extensionsWidgets.ts
│ │ │ │ │ ├── extensionsWorkbenchService.ts
│ │ │ │ │ ├── fileBasedRecommendations.ts
│ │ │ │ │ ├── keymapRecommendations.ts
│ │ │ │ │ ├── languageRecommendations.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── extension.css
│ │ │ │ │ │ ├── extensionActions.css
│ │ │ │ │ │ ├── extensionEditor.css
│ │ │ │ │ │ ├── extensionsViewlet.css
│ │ │ │ │ │ ├── extensionsWidgets.css
│ │ │ │ │ │ └── runtimeExtensionsEditor.css
│ │ │ │ │ ├── remoteRecommendations.ts
│ │ │ │ │ ├── unsupportedExtensionsMigrationContribution.ts
│ │ │ │ │ ├── webRecommendations.ts
│ │ │ │ │ └── workspaceRecommendations.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── extensionQuery.ts
│ │ │ │ │ ├── extensions.ts
│ │ │ │ │ ├── extensionsFileTemplate.ts
│ │ │ │ │ ├── extensionsInput.ts
│ │ │ │ │ ├── extensionsUtils.ts
│ │ │ │ │ ├── reportExtensionIssueAction.ts
│ │ │ │ │ └── runtimeExtensionsInput.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── debugExtensionHostAction.ts
│ │ │ │ │ ├── extensionProfileService.ts
│ │ │ │ │ ├── extensions.contribution.ts
│ │ │ │ │ ├── extensionsActions.ts
│ │ │ │ │ ├── extensionsAutoProfiler.ts
│ │ │ │ │ ├── extensionsSlowActions.ts
│ │ │ │ │ ├── remoteExtensionsInit.ts
│ │ │ │ │ └── runtimeExtensionsEditor.ts
│ │ │ │ └── test/
│ │ │ │ ├── common/
│ │ │ │ │ └── extensionQuery.test.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── extension.test.ts
│ │ │ │ ├── extensionRecommendationsService.test.ts
│ │ │ │ ├── extensionsActions.test.ts
│ │ │ │ ├── extensionsViews.test.ts
│ │ │ │ └── extensionsWorkbenchService.test.ts
│ │ │ ├── externalTerminal/
│ │ │ │ ├── browser/
│ │ │ │ │ └── externalTerminal.contribution.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── externalTerminal.contribution.ts
│ │ │ │ └── node/
│ │ │ │ ├── TerminalHelper.scpt
│ │ │ │ └── iTermHelper.scpt
│ │ │ ├── externalUriOpener/
│ │ │ │ ├── common/
│ │ │ │ │ ├── configuration.ts
│ │ │ │ │ ├── contributedOpeners.ts
│ │ │ │ │ ├── externalUriOpener.contribution.ts
│ │ │ │ │ └── externalUriOpenerService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── externalUriOpenerService.test.ts
│ │ │ ├── files/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── editors/
│ │ │ │ │ │ ├── binaryFileEditor.ts
│ │ │ │ │ │ ├── fileEditorHandler.ts
│ │ │ │ │ │ ├── fileEditorInput.ts
│ │ │ │ │ │ ├── textFileEditor.ts
│ │ │ │ │ │ ├── textFileEditorTracker.ts
│ │ │ │ │ │ └── textFileSaveErrorHandler.ts
│ │ │ │ │ ├── explorerFileContrib.ts
│ │ │ │ │ ├── explorerService.ts
│ │ │ │ │ ├── explorerViewlet.ts
│ │ │ │ │ ├── fileActions.contribution.ts
│ │ │ │ │ ├── fileActions.ts
│ │ │ │ │ ├── fileCommands.ts
│ │ │ │ │ ├── fileConstants.ts
│ │ │ │ │ ├── fileImportExport.ts
│ │ │ │ │ ├── files.contribution.ts
│ │ │ │ │ ├── files.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── explorerviewlet.css
│ │ │ │ │ ├── views/
│ │ │ │ │ │ ├── emptyView.ts
│ │ │ │ │ │ ├── explorerDecorationsProvider.ts
│ │ │ │ │ │ ├── explorerView.ts
│ │ │ │ │ │ ├── explorerViewer.ts
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── openeditors.css
│ │ │ │ │ │ └── openEditorsView.ts
│ │ │ │ │ └── workspaceWatcher.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── dirtyFilesIndicator.ts
│ │ │ │ │ ├── explorerFileNestingTrie.ts
│ │ │ │ │ ├── explorerModel.ts
│ │ │ │ │ └── files.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── fileActions.contribution.ts
│ │ │ │ │ └── fileCommands.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── editorAutoSave.test.ts
│ │ │ │ ├── explorerFileNestingTrie.test.ts
│ │ │ │ ├── explorerFindProvider.test.ts
│ │ │ │ ├── explorerModel.test.ts
│ │ │ │ ├── explorerView.test.ts
│ │ │ │ ├── fileActions.test.ts
│ │ │ │ ├── fileEditorInput.test.ts
│ │ │ │ ├── fileOnDiskProvider.test.ts
│ │ │ │ └── textFileEditorTracker.test.ts
│ │ │ ├── folding/
│ │ │ │ └── browser/
│ │ │ │ └── folding.contribution.ts
│ │ │ ├── format/
│ │ │ │ └── browser/
│ │ │ │ ├── format.contribution.ts
│ │ │ │ ├── formatActionsMultiple.ts
│ │ │ │ ├── formatActionsNone.ts
│ │ │ │ └── formatModified.ts
│ │ │ ├── inlayHints/
│ │ │ │ └── browser/
│ │ │ │ └── inlayHintsAccessibilty.ts
│ │ │ ├── inlineChat/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── inlineChat.contribution.ts
│ │ │ │ │ ├── inlineChatAccessibilityHelp.ts
│ │ │ │ │ ├── inlineChatAccessibleView.ts
│ │ │ │ │ ├── inlineChatActions.ts
│ │ │ │ │ ├── inlineChatController.ts
│ │ │ │ │ ├── inlineChatCurrentLine.ts
│ │ │ │ │ ├── inlineChatNotebook.ts
│ │ │ │ │ ├── inlineChatSession.ts
│ │ │ │ │ ├── inlineChatSessionService.ts
│ │ │ │ │ ├── inlineChatSessionServiceImpl.ts
│ │ │ │ │ ├── inlineChatStrategies.ts
│ │ │ │ │ ├── inlineChatWidget.ts
│ │ │ │ │ ├── inlineChatZoneWidget.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── inlineChat.css
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── inlineChat.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── inlineChat.contribution.ts
│ │ │ │ │ └── inlineChatActions.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ ├── InlineChatSession_Apply_Code_s_preview_should_be_easier_to_undo_esc__7537.1.snap
│ │ │ │ │ └── InlineChatSession_Apply_Code_s_preview_should_be_easier_to_undo_esc__7537.2.snap
│ │ │ │ ├── inlineChatController.test.ts
│ │ │ │ ├── inlineChatSession.test.ts
│ │ │ │ ├── inlineChatStrategies.test.ts
│ │ │ │ └── testWorkerService.ts
│ │ │ ├── inlineCompletions/
│ │ │ │ └── browser/
│ │ │ │ ├── inlineCompletionLanguageStatusBarContribution.ts
│ │ │ │ └── inlineCompletions.contribution.ts
│ │ │ ├── interactive/
│ │ │ │ └── browser/
│ │ │ │ ├── interactive.contribution.ts
│ │ │ │ ├── interactiveCommon.ts
│ │ │ │ ├── interactiveDocumentService.ts
│ │ │ │ ├── interactiveEditor.css
│ │ │ │ ├── interactiveEditor.ts
│ │ │ │ ├── interactiveEditorInput.ts
│ │ │ │ ├── interactiveHistoryService.ts
│ │ │ │ ├── media/
│ │ │ │ │ └── interactive.css
│ │ │ │ └── replInputHintContentWidget.ts
│ │ │ ├── issue/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── baseIssueReporterService.ts
│ │ │ │ │ ├── issue.contribution.ts
│ │ │ │ │ ├── issueFormService.ts
│ │ │ │ │ ├── issueQuickAccess.ts
│ │ │ │ │ ├── issueReporterModel.ts
│ │ │ │ │ ├── issueReporterPage.ts
│ │ │ │ │ ├── issueReporterService.ts
│ │ │ │ │ ├── issueService.ts
│ │ │ │ │ ├── issueTroubleshoot.ts
│ │ │ │ │ └── media/
│ │ │ │ │ └── issueReporter.css
│ │ │ │ ├── common/
│ │ │ │ │ ├── issue.contribution.ts
│ │ │ │ │ ├── issue.ts
│ │ │ │ │ └── issueReporterUtil.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── issue.contribution.ts
│ │ │ │ │ ├── issueReporterService.ts
│ │ │ │ │ ├── issueService.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── issueReporter.css
│ │ │ │ │ ├── nativeIssueFormService.ts
│ │ │ │ │ ├── process.contribution.ts
│ │ │ │ │ ├── processMainService.ts
│ │ │ │ │ └── processService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── testReporterModel.test.ts
│ │ │ ├── keybindings/
│ │ │ │ └── browser/
│ │ │ │ └── keybindings.contribution.ts
│ │ │ ├── languageDetection/
│ │ │ │ └── browser/
│ │ │ │ └── languageDetection.contribution.ts
│ │ │ ├── languageStatus/
│ │ │ │ └── browser/
│ │ │ │ ├── languageStatus.contribution.ts
│ │ │ │ ├── languageStatus.ts
│ │ │ │ └── media/
│ │ │ │ └── languageStatus.css
│ │ │ ├── limitIndicator/
│ │ │ │ └── browser/
│ │ │ │ └── limitIndicator.contribution.ts
│ │ │ ├── list/
│ │ │ │ └── browser/
│ │ │ │ ├── list.contribution.ts
│ │ │ │ ├── listResizeColumnAction.ts
│ │ │ │ └── tableColumnResizeQuickPick.ts
│ │ │ ├── localHistory/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── localHistory.contribution.ts
│ │ │ │ │ ├── localHistory.ts
│ │ │ │ │ ├── localHistoryCommands.ts
│ │ │ │ │ ├── localHistoryFileSystemProvider.ts
│ │ │ │ │ └── localHistoryTimeline.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── localHistory.contribution.ts
│ │ │ │ └── localHistoryCommands.ts
│ │ │ ├── localization/
│ │ │ │ ├── browser/
│ │ │ │ │ └── localization.contribution.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── localization.contribution.ts
│ │ │ │ │ └── localizationsActions.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── localization.contribution.ts
│ │ │ │ └── minimalTranslations.ts
│ │ │ ├── logs/
│ │ │ │ ├── browser/
│ │ │ │ │ └── logs.contribution.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── defaultLogLevels.ts
│ │ │ │ │ ├── logs.contribution.ts
│ │ │ │ │ ├── logsActions.ts
│ │ │ │ │ └── logsDataCleaner.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── logs.contribution.ts
│ │ │ │ └── logsActions.ts
│ │ │ ├── markdown/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── markdownDocumentRenderer.ts
│ │ │ │ │ ├── markdownSettingRenderer.ts
│ │ │ │ │ └── markedGfmHeadingIdPlugin.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── markdownSettingRenderer.test.ts
│ │ │ ├── markers/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── markers.contribution.ts
│ │ │ │ │ ├── markers.ts
│ │ │ │ │ ├── markersFileDecorations.ts
│ │ │ │ │ ├── markersFilterOptions.ts
│ │ │ │ │ ├── markersModel.ts
│ │ │ │ │ ├── markersTable.ts
│ │ │ │ │ ├── markersTreeViewer.ts
│ │ │ │ │ ├── markersView.ts
│ │ │ │ │ ├── markersViewActions.css
│ │ │ │ │ ├── markersViewActions.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── markers.css
│ │ │ │ │ └── messages.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── markers.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── markersModel.test.ts
│ │ │ ├── mcp/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── mcp.contribution.ts
│ │ │ │ │ ├── mcpCommands.ts
│ │ │ │ │ ├── mcpCommandsAddConfiguration.ts
│ │ │ │ │ ├── mcpDiscovery.ts
│ │ │ │ │ ├── mcpLanguageFeatures.ts
│ │ │ │ │ └── mcpUrlHandler.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── discovery/
│ │ │ │ │ │ ├── configMcpDiscovery.ts
│ │ │ │ │ │ ├── extensionMcpDiscovery.ts
│ │ │ │ │ │ ├── mcpDiscovery.ts
│ │ │ │ │ │ ├── nativeMcpDiscoveryAbstract.ts
│ │ │ │ │ │ ├── nativeMcpDiscoveryAdapters.ts
│ │ │ │ │ │ ├── nativeMcpRemoteDiscovery.ts
│ │ │ │ │ │ └── workspaceMcpDiscoveryAdapter.ts
│ │ │ │ │ ├── mcpConfigFileUtils.ts
│ │ │ │ │ ├── mcpConfigPathsService.ts
│ │ │ │ │ ├── mcpConfiguration.ts
│ │ │ │ │ ├── mcpContextKeys.ts
│ │ │ │ │ ├── mcpRegistry.ts
│ │ │ │ │ ├── mcpRegistryInputStorage.ts
│ │ │ │ │ ├── mcpRegistryTypes.ts
│ │ │ │ │ ├── mcpServer.ts
│ │ │ │ │ ├── mcpServerConnection.ts
│ │ │ │ │ ├── mcpServerRequestHandler.ts
│ │ │ │ │ ├── mcpService.ts
│ │ │ │ │ ├── mcpTypes.ts
│ │ │ │ │ └── modelContextProtocol.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── mcp.contribution.ts
│ │ │ │ │ └── nativeMpcDiscovery.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ ├── mcpRegistry.test.ts
│ │ │ │ ├── mcpRegistryInputStorage.test.ts
│ │ │ │ ├── mcpRegistryTypes.ts
│ │ │ │ ├── mcpServerConnection.test.ts
│ │ │ │ └── mcpServerRequestHandler.test.ts
│ │ │ ├── mergeEditor/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── commands/
│ │ │ │ │ │ ├── commands.ts
│ │ │ │ │ │ └── devCommands.ts
│ │ │ │ │ ├── mergeEditor.contribution.ts
│ │ │ │ │ ├── mergeEditorAccessibilityHelp.ts
│ │ │ │ │ ├── mergeEditorInput.ts
│ │ │ │ │ ├── mergeEditorInputModel.ts
│ │ │ │ │ ├── mergeEditorSerializer.ts
│ │ │ │ │ ├── mergeMarkers/
│ │ │ │ │ │ └── mergeMarkersController.ts
│ │ │ │ │ ├── model/
│ │ │ │ │ │ ├── diffComputer.ts
│ │ │ │ │ │ ├── editing.ts
│ │ │ │ │ │ ├── lineRange.ts
│ │ │ │ │ │ ├── mapping.ts
│ │ │ │ │ │ ├── mergeEditorModel.ts
│ │ │ │ │ │ ├── modifiedBaseRange.ts
│ │ │ │ │ │ ├── rangeUtils.ts
│ │ │ │ │ │ └── textModelDiffs.ts
│ │ │ │ │ ├── telemetry.ts
│ │ │ │ │ ├── utils.ts
│ │ │ │ │ └── view/
│ │ │ │ │ ├── colors.ts
│ │ │ │ │ ├── conflictActions.ts
│ │ │ │ │ ├── editorGutter.ts
│ │ │ │ │ ├── editors/
│ │ │ │ │ │ ├── baseCodeEditorView.ts
│ │ │ │ │ │ ├── codeEditorView.ts
│ │ │ │ │ │ ├── inputCodeEditorView.ts
│ │ │ │ │ │ └── resultCodeEditorView.ts
│ │ │ │ │ ├── fixedZoneWidget.ts
│ │ │ │ │ ├── lineAlignment.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── mergeEditor.css
│ │ │ │ │ ├── mergeEditor.ts
│ │ │ │ │ ├── scrollSynchronizer.ts
│ │ │ │ │ ├── viewModel.ts
│ │ │ │ │ └── viewZones.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── mergeEditor.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── devCommands.ts
│ │ │ │ │ └── mergeEditor.contribution.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── mapping.test.ts
│ │ │ │ └── model.test.ts
│ │ │ ├── multiDiffEditor/
│ │ │ │ └── browser/
│ │ │ │ ├── actions.ts
│ │ │ │ ├── icons.contribution.ts
│ │ │ │ ├── multiDiffEditor.contribution.ts
│ │ │ │ ├── multiDiffEditor.ts
│ │ │ │ ├── multiDiffEditorInput.ts
│ │ │ │ ├── multiDiffSourceResolverService.ts
│ │ │ │ └── scmMultiDiffSourceResolver.ts
│ │ │ ├── notebook/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── contrib/
│ │ │ │ │ │ ├── cellCommands/
│ │ │ │ │ │ │ └── cellCommands.ts
│ │ │ │ │ │ ├── cellDiagnostics/
│ │ │ │ │ │ │ ├── cellDiagnosticEditorContrib.ts
│ │ │ │ │ │ │ ├── cellDiagnostics.ts
│ │ │ │ │ │ │ ├── cellDiagnosticsActions.ts
│ │ │ │ │ │ │ └── diagnosticCellStatusBarContrib.ts
│ │ │ │ │ │ ├── cellStatusBar/
│ │ │ │ │ │ │ ├── contributedStatusBarItemController.ts
│ │ │ │ │ │ │ ├── executionStatusBarItemController.ts
│ │ │ │ │ │ │ ├── notebookVisibleCellObserver.ts
│ │ │ │ │ │ │ └── statusBarProviders.ts
│ │ │ │ │ │ ├── clipboard/
│ │ │ │ │ │ │ └── notebookClipboard.ts
│ │ │ │ │ │ ├── debug/
│ │ │ │ │ │ │ ├── notebookBreakpoints.ts
│ │ │ │ │ │ │ ├── notebookCellPausing.ts
│ │ │ │ │ │ │ └── notebookDebugDecorations.ts
│ │ │ │ │ │ ├── editorHint/
│ │ │ │ │ │ │ └── emptyCellEditorHint.ts
│ │ │ │ │ │ ├── editorStatusBar/
│ │ │ │ │ │ │ └── editorStatusBar.ts
│ │ │ │ │ │ ├── execute/
│ │ │ │ │ │ │ └── executionEditorProgress.ts
│ │ │ │ │ │ ├── find/
│ │ │ │ │ │ │ ├── findFilters.ts
│ │ │ │ │ │ │ ├── findMatchDecorationModel.ts
│ │ │ │ │ │ │ ├── findModel.ts
│ │ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ │ └── notebookFind.css
│ │ │ │ │ │ │ ├── notebookFind.ts
│ │ │ │ │ │ │ ├── notebookFindReplaceWidget.css
│ │ │ │ │ │ │ ├── notebookFindReplaceWidget.ts
│ │ │ │ │ │ │ └── notebookFindWidget.ts
│ │ │ │ │ │ ├── format/
│ │ │ │ │ │ │ └── formatting.ts
│ │ │ │ │ │ ├── gettingStarted/
│ │ │ │ │ │ │ └── notebookGettingStarted.ts
│ │ │ │ │ │ ├── kernelDetection/
│ │ │ │ │ │ │ └── notebookKernelDetection.ts
│ │ │ │ │ │ ├── layout/
│ │ │ │ │ │ │ └── layoutActions.ts
│ │ │ │ │ │ ├── marker/
│ │ │ │ │ │ │ └── markerProvider.ts
│ │ │ │ │ │ ├── multicursor/
│ │ │ │ │ │ │ ├── notebookMulticursor.ts
│ │ │ │ │ │ │ └── notebookSelectionHighlight.ts
│ │ │ │ │ │ ├── navigation/
│ │ │ │ │ │ │ └── arrow.ts
│ │ │ │ │ │ ├── notebookVariables/
│ │ │ │ │ │ │ ├── notebookInlineVariables.ts
│ │ │ │ │ │ │ ├── notebookVariableCommands.ts
│ │ │ │ │ │ │ ├── notebookVariableContextKeys.ts
│ │ │ │ │ │ │ ├── notebookVariables.ts
│ │ │ │ │ │ │ ├── notebookVariablesDataSource.ts
│ │ │ │ │ │ │ ├── notebookVariablesTree.ts
│ │ │ │ │ │ │ └── notebookVariablesView.ts
│ │ │ │ │ │ ├── outline/
│ │ │ │ │ │ │ └── notebookOutline.ts
│ │ │ │ │ │ ├── profile/
│ │ │ │ │ │ │ └── notebookProfile.ts
│ │ │ │ │ │ ├── saveParticipants/
│ │ │ │ │ │ │ └── saveParticipants.ts
│ │ │ │ │ │ ├── troubleshoot/
│ │ │ │ │ │ │ └── layout.ts
│ │ │ │ │ │ ├── undoRedo/
│ │ │ │ │ │ │ └── notebookUndoRedo.ts
│ │ │ │ │ │ └── viewportWarmup/
│ │ │ │ │ │ └── viewportWarmup.ts
│ │ │ │ │ ├── controller/
│ │ │ │ │ │ ├── apiActions.ts
│ │ │ │ │ │ ├── cellOperations.ts
│ │ │ │ │ │ ├── cellOutputActions.ts
│ │ │ │ │ │ ├── chat/
│ │ │ │ │ │ │ ├── cellChatActions.ts
│ │ │ │ │ │ │ ├── notebook.chat.contribution.ts
│ │ │ │ │ │ │ ├── notebookChatContext.ts
│ │ │ │ │ │ │ └── notebookChatController.ts
│ │ │ │ │ │ ├── coreActions.ts
│ │ │ │ │ │ ├── editActions.ts
│ │ │ │ │ │ ├── executeActions.ts
│ │ │ │ │ │ ├── foldingController.ts
│ │ │ │ │ │ ├── insertCellActions.ts
│ │ │ │ │ │ ├── layoutActions.ts
│ │ │ │ │ │ ├── notebookIndentationActions.ts
│ │ │ │ │ │ ├── sectionActions.ts
│ │ │ │ │ │ └── variablesActions.ts
│ │ │ │ │ ├── diff/
│ │ │ │ │ │ ├── diffCellEditorOptions.ts
│ │ │ │ │ │ ├── diffComponents.ts
│ │ │ │ │ │ ├── diffElementOutputs.ts
│ │ │ │ │ │ ├── diffElementViewModel.ts
│ │ │ │ │ │ ├── diffNestedCellViewModel.ts
│ │ │ │ │ │ ├── editorHeightCalculator.ts
│ │ │ │ │ │ ├── eventDispatcher.ts
│ │ │ │ │ │ ├── inlineDiff/
│ │ │ │ │ │ │ ├── notebookCellDiffDecorator.ts
│ │ │ │ │ │ │ ├── notebookDeletedCellDecorator.ts
│ │ │ │ │ │ │ ├── notebookInlineDiff.ts
│ │ │ │ │ │ │ ├── notebookInlineDiffWidget.ts
│ │ │ │ │ │ │ ├── notebookInsertedCellDecorator.ts
│ │ │ │ │ │ │ ├── notebookModifiedCellDecorator.ts
│ │ │ │ │ │ │ ├── notebookOriginalCellModelFactory.ts
│ │ │ │ │ │ │ └── notebookOriginalModelRefFactory.ts
│ │ │ │ │ │ ├── notebookDiff.css
│ │ │ │ │ │ ├── notebookDiffActions.ts
│ │ │ │ │ │ ├── notebookDiffEditor.ts
│ │ │ │ │ │ ├── notebookDiffEditorBrowser.ts
│ │ │ │ │ │ ├── notebookDiffList.ts
│ │ │ │ │ │ ├── notebookDiffOverviewRuler.ts
│ │ │ │ │ │ ├── notebookDiffViewModel.ts
│ │ │ │ │ │ ├── notebookMultiDiffEditor.ts
│ │ │ │ │ │ ├── notebookMultiDiffEditorInput.ts
│ │ │ │ │ │ └── unchangedEditorRegions.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── notebook.css
│ │ │ │ │ │ ├── notebookCellChat.css
│ │ │ │ │ │ ├── notebookCellEditorHint.css
│ │ │ │ │ │ ├── notebookCellInsertToolbar.css
│ │ │ │ │ │ ├── notebookCellOutput.css
│ │ │ │ │ │ ├── notebookCellStatusBar.css
│ │ │ │ │ │ ├── notebookCellTitleToolbar.css
│ │ │ │ │ │ ├── notebookChatEditController.css
│ │ │ │ │ │ ├── notebookChatEditorOverlay.css
│ │ │ │ │ │ ├── notebookDnd.css
│ │ │ │ │ │ ├── notebookEditorStickyScroll.css
│ │ │ │ │ │ ├── notebookFocusIndicator.css
│ │ │ │ │ │ ├── notebookFolding.css
│ │ │ │ │ │ ├── notebookKernelActionViewItem.css
│ │ │ │ │ │ ├── notebookOutline.css
│ │ │ │ │ │ └── notebookToolbar.css
│ │ │ │ │ ├── notebook.contribution.ts
│ │ │ │ │ ├── notebookAccessibilityHelp.ts
│ │ │ │ │ ├── notebookAccessibilityProvider.ts
│ │ │ │ │ ├── notebookAccessibleView.ts
│ │ │ │ │ ├── notebookBrowser.ts
│ │ │ │ │ ├── notebookEditor.ts
│ │ │ │ │ ├── notebookEditorExtensions.ts
│ │ │ │ │ ├── notebookEditorWidget.ts
│ │ │ │ │ ├── notebookExtensionPoint.ts
│ │ │ │ │ ├── notebookIcons.ts
│ │ │ │ │ ├── notebookLogger.ts
│ │ │ │ │ ├── notebookOptions.ts
│ │ │ │ │ ├── notebookViewEvents.ts
│ │ │ │ │ ├── replEditorAccessibleView.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ ├── notebookCellStatusBarServiceImpl.ts
│ │ │ │ │ │ ├── notebookEditorService.ts
│ │ │ │ │ │ ├── notebookEditorServiceImpl.ts
│ │ │ │ │ │ ├── notebookExecutionServiceImpl.ts
│ │ │ │ │ │ ├── notebookExecutionStateServiceImpl.ts
│ │ │ │ │ │ ├── notebookKernelHistoryServiceImpl.ts
│ │ │ │ │ │ ├── notebookKernelServiceImpl.ts
│ │ │ │ │ │ ├── notebookKeymapServiceImpl.ts
│ │ │ │ │ │ ├── notebookLoggingServiceImpl.ts
│ │ │ │ │ │ ├── notebookRendererMessagingServiceImpl.ts
│ │ │ │ │ │ ├── notebookServiceImpl.ts
│ │ │ │ │ │ └── notebookWorkerServiceImpl.ts
│ │ │ │ │ ├── view/
│ │ │ │ │ │ ├── cellPart.ts
│ │ │ │ │ │ ├── cellParts/
│ │ │ │ │ │ │ ├── cellActionView.ts
│ │ │ │ │ │ │ ├── cellComments.ts
│ │ │ │ │ │ │ ├── cellContextKeys.ts
│ │ │ │ │ │ │ ├── cellDecorations.ts
│ │ │ │ │ │ │ ├── cellDnd.ts
│ │ │ │ │ │ │ ├── cellDragRenderer.ts
│ │ │ │ │ │ │ ├── cellEditorOptions.ts
│ │ │ │ │ │ │ ├── cellExecution.ts
│ │ │ │ │ │ │ ├── cellFocus.ts
│ │ │ │ │ │ │ ├── cellFocusIndicator.ts
│ │ │ │ │ │ │ ├── cellOutput.ts
│ │ │ │ │ │ │ ├── cellProgressBar.ts
│ │ │ │ │ │ │ ├── cellStatusPart.ts
│ │ │ │ │ │ │ ├── cellToolbarStickyScroll.ts
│ │ │ │ │ │ │ ├── cellToolbars.ts
│ │ │ │ │ │ │ ├── cellWidgets.ts
│ │ │ │ │ │ │ ├── chat/
│ │ │ │ │ │ │ │ └── cellChatPart.ts
│ │ │ │ │ │ │ ├── codeCell.ts
│ │ │ │ │ │ │ ├── codeCellExecutionIcon.ts
│ │ │ │ │ │ │ ├── codeCellRunToolbar.ts
│ │ │ │ │ │ │ ├── collapsedCellInput.ts
│ │ │ │ │ │ │ ├── collapsedCellOutput.ts
│ │ │ │ │ │ │ ├── foldedCellHint.ts
│ │ │ │ │ │ │ └── markupCell.ts
│ │ │ │ │ │ ├── notebookCellAnchor.ts
│ │ │ │ │ │ ├── notebookCellEditorPool.ts
│ │ │ │ │ │ ├── notebookCellList.ts
│ │ │ │ │ │ ├── notebookCellListView.ts
│ │ │ │ │ │ ├── notebookRenderingCommon.ts
│ │ │ │ │ │ └── renderers/
│ │ │ │ │ │ ├── backLayerWebView.ts
│ │ │ │ │ │ ├── cellRenderer.ts
│ │ │ │ │ │ ├── webviewMessages.ts
│ │ │ │ │ │ ├── webviewPreloads.ts
│ │ │ │ │ │ └── webviewThemeMapping.ts
│ │ │ │ │ ├── viewModel/
│ │ │ │ │ │ ├── OutlineEntry.ts
│ │ │ │ │ │ ├── baseCellViewModel.ts
│ │ │ │ │ │ ├── cellEdit.ts
│ │ │ │ │ │ ├── cellEditorOptions.ts
│ │ │ │ │ │ ├── cellOutputTextHelper.ts
│ │ │ │ │ │ ├── cellOutputViewModel.ts
│ │ │ │ │ │ ├── cellSelectionCollection.ts
│ │ │ │ │ │ ├── codeCellViewModel.ts
│ │ │ │ │ │ ├── eventDispatcher.ts
│ │ │ │ │ │ ├── foldingModel.ts
│ │ │ │ │ │ ├── markupCellViewModel.ts
│ │ │ │ │ │ ├── notebookOutlineDataSource.ts
│ │ │ │ │ │ ├── notebookOutlineDataSourceFactory.ts
│ │ │ │ │ │ ├── notebookOutlineEntryFactory.ts
│ │ │ │ │ │ ├── notebookViewModelImpl.ts
│ │ │ │ │ │ └── viewContext.ts
│ │ │ │ │ └── viewParts/
│ │ │ │ │ ├── notebookCellOverlays.ts
│ │ │ │ │ ├── notebookEditorStickyScroll.ts
│ │ │ │ │ ├── notebookEditorToolbar.ts
│ │ │ │ │ ├── notebookEditorWidgetContextKeys.ts
│ │ │ │ │ ├── notebookHorizontalTracker.ts
│ │ │ │ │ ├── notebookKernelQuickPickStrategy.ts
│ │ │ │ │ ├── notebookKernelView.ts
│ │ │ │ │ ├── notebookOverviewRuler.ts
│ │ │ │ │ ├── notebookTopCellToolbar.ts
│ │ │ │ │ └── notebookViewZones.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── model/
│ │ │ │ │ │ ├── cellEdit.ts
│ │ │ │ │ │ ├── notebookCellOutputTextModel.ts
│ │ │ │ │ │ ├── notebookCellTextModel.ts
│ │ │ │ │ │ ├── notebookMetadataTextModel.ts
│ │ │ │ │ │ └── notebookTextModel.ts
│ │ │ │ │ ├── notebookCellStatusBarService.ts
│ │ │ │ │ ├── notebookCommon.ts
│ │ │ │ │ ├── notebookContextKeys.ts
│ │ │ │ │ ├── notebookDiff.ts
│ │ │ │ │ ├── notebookDiffEditorInput.ts
│ │ │ │ │ ├── notebookEditorInput.ts
│ │ │ │ │ ├── notebookEditorModel.ts
│ │ │ │ │ ├── notebookEditorModelResolverService.ts
│ │ │ │ │ ├── notebookEditorModelResolverServiceImpl.ts
│ │ │ │ │ ├── notebookExecutionService.ts
│ │ │ │ │ ├── notebookExecutionStateService.ts
│ │ │ │ │ ├── notebookKernelService.ts
│ │ │ │ │ ├── notebookKeymapService.ts
│ │ │ │ │ ├── notebookLoggingService.ts
│ │ │ │ │ ├── notebookOutputRenderer.ts
│ │ │ │ │ ├── notebookPerformance.ts
│ │ │ │ │ ├── notebookProvider.ts
│ │ │ │ │ ├── notebookRange.ts
│ │ │ │ │ ├── notebookRendererMessagingService.ts
│ │ │ │ │ ├── notebookService.ts
│ │ │ │ │ └── services/
│ │ │ │ │ ├── notebookCellMatching.ts
│ │ │ │ │ ├── notebookWebWorker.ts
│ │ │ │ │ ├── notebookWebWorkerMain.ts
│ │ │ │ │ └── notebookWorkerService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── NotebookEditorWidgetService.test.ts
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ ├── NotebookEditorStickyScroll_test0__should_render_empty___scrollTop_at_0.0.snap
│ │ │ │ │ ├── NotebookEditorStickyScroll_test1__should_render_0-_1___visible_range_3-_8.0.snap
│ │ │ │ │ ├── NotebookEditorStickyScroll_test2__should_render_0____visible_range_6-_9_so_collapsing_next_2_against_following_section.0.snap
│ │ │ │ │ ├── NotebookEditorStickyScroll_test3__should_render_0-_2___collapsing_against_equivalent_level_header.0.snap
│ │ │ │ │ ├── NotebookEditorStickyScroll_test4__should_render_0____scrolltop_halfway_through_cell_0.0.snap
│ │ │ │ │ ├── NotebookEditorStickyScroll_test5__should_render_0-_2___scrolltop_halfway_through_cell_2.0.snap
│ │ │ │ │ ├── NotebookEditorStickyScroll_test6__should_render_6-_7___scrolltop_halfway_through_cell_7.0.snap
│ │ │ │ │ └── NotebookEditorStickyScroll_test7__should_render_0-_1___collapsing_against_next_section.0.snap
│ │ │ │ ├── cellDecorations.test.ts
│ │ │ │ ├── cellDnd.test.ts
│ │ │ │ ├── cellOperations.test.ts
│ │ │ │ ├── cellOutput.test.ts
│ │ │ │ ├── contrib/
│ │ │ │ │ ├── contributedStatusBarItemController.test.ts
│ │ │ │ │ ├── executionStatusBarItem.test.ts
│ │ │ │ │ ├── find.test.ts
│ │ │ │ │ ├── layoutActions.test.ts
│ │ │ │ │ ├── notebookCellDiagnostics.test.ts
│ │ │ │ │ ├── notebookClipboard.test.ts
│ │ │ │ │ ├── notebookOutline.test.ts
│ │ │ │ │ ├── notebookOutlineViewProviders.test.ts
│ │ │ │ │ ├── notebookSymbols.test.ts
│ │ │ │ │ ├── notebookUndoRedo.test.ts
│ │ │ │ │ └── outputCopyTests.test.ts
│ │ │ │ ├── diff/
│ │ │ │ │ ├── editorHeightCalculator.test.ts
│ │ │ │ │ ├── notebookDiff.test.ts
│ │ │ │ │ └── notebookDiffService.test.ts
│ │ │ │ ├── notebookBrowser.test.ts
│ │ │ │ ├── notebookCellAnchor.test.ts
│ │ │ │ ├── notebookCellList.test.ts
│ │ │ │ ├── notebookCommon.test.ts
│ │ │ │ ├── notebookEditor.test.ts
│ │ │ │ ├── notebookEditorModel.test.ts
│ │ │ │ ├── notebookExecutionService.test.ts
│ │ │ │ ├── notebookExecutionStateService.test.ts
│ │ │ │ ├── notebookFolding.test.ts
│ │ │ │ ├── notebookKernelHistory.test.ts
│ │ │ │ ├── notebookKernelService.test.ts
│ │ │ │ ├── notebookRendererMessagingService.test.ts
│ │ │ │ ├── notebookSelection.test.ts
│ │ │ │ ├── notebookServiceImpl.test.ts
│ │ │ │ ├── notebookStickyScroll.test.ts
│ │ │ │ ├── notebookTextModel.test.ts
│ │ │ │ ├── notebookVariablesDataSource.test.ts
│ │ │ │ ├── notebookViewModel.test.ts
│ │ │ │ ├── notebookViewZones.test.ts
│ │ │ │ ├── notebookWorkbenchToolbar.test.ts
│ │ │ │ └── testNotebookEditor.ts
│ │ │ ├── outline/
│ │ │ │ └── browser/
│ │ │ │ ├── outline.contribution.ts
│ │ │ │ ├── outline.ts
│ │ │ │ ├── outlineActions.ts
│ │ │ │ ├── outlinePane.css
│ │ │ │ ├── outlinePane.ts
│ │ │ │ └── outlineViewState.ts
│ │ │ ├── output/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── output.contribution.ts
│ │ │ │ │ ├── output.css
│ │ │ │ │ ├── outputLinkProvider.ts
│ │ │ │ │ ├── outputServices.ts
│ │ │ │ │ └── outputView.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── outputChannelModel.ts
│ │ │ │ │ ├── outputLinkComputer.ts
│ │ │ │ │ └── outputLinkComputerMain.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── outputChannelModel.test.ts
│ │ │ │ └── outputLinkProvider.test.ts
│ │ │ ├── performance/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── inputLatencyContrib.ts
│ │ │ │ │ ├── performance.contribution.ts
│ │ │ │ │ ├── performance.web.contribution.ts
│ │ │ │ │ ├── perfviewEditor.ts
│ │ │ │ │ └── startupTimings.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── performance.contribution.ts
│ │ │ │ ├── rendererAutoProfiler.ts
│ │ │ │ ├── startupProfiler.ts
│ │ │ │ └── startupTimings.ts
│ │ │ ├── preferences/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── keybindingWidgets.ts
│ │ │ │ │ ├── keybindingsEditor.ts
│ │ │ │ │ ├── keybindingsEditorContribution.ts
│ │ │ │ │ ├── keyboardLayoutPicker.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── keybindings.css
│ │ │ │ │ │ ├── keybindingsEditor.css
│ │ │ │ │ │ ├── preferences.css
│ │ │ │ │ │ ├── settingsEditor2.css
│ │ │ │ │ │ └── settingsWidgets.css
│ │ │ │ │ ├── preferences.contribution.ts
│ │ │ │ │ ├── preferencesActions.ts
│ │ │ │ │ ├── preferencesEditor.ts
│ │ │ │ │ ├── preferencesIcons.ts
│ │ │ │ │ ├── preferencesRenderers.ts
│ │ │ │ │ ├── preferencesSearch.ts
│ │ │ │ │ ├── preferencesWidgets.ts
│ │ │ │ │ ├── settingsEditor2.ts
│ │ │ │ │ ├── settingsEditorSettingIndicators.ts
│ │ │ │ │ ├── settingsLayout.ts
│ │ │ │ │ ├── settingsSearchMenu.ts
│ │ │ │ │ ├── settingsTree.ts
│ │ │ │ │ ├── settingsTreeModels.ts
│ │ │ │ │ ├── settingsWidgets.ts
│ │ │ │ │ └── tocTree.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── preferences.ts
│ │ │ │ │ ├── preferencesContribution.ts
│ │ │ │ │ ├── settingsEditorColorRegistry.ts
│ │ │ │ │ ├── settingsFilesystemProvider.ts
│ │ │ │ │ └── smartSnippetInserter.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── keybindingsEditorContribution.test.ts
│ │ │ │ │ └── settingsTreeModels.test.ts
│ │ │ │ └── common/
│ │ │ │ └── smartSnippetInserter.test.ts
│ │ │ ├── quickaccess/
│ │ │ │ └── browser/
│ │ │ │ ├── commandsQuickAccess.ts
│ │ │ │ ├── quickAccess.contribution.ts
│ │ │ │ └── viewQuickAccess.ts
│ │ │ ├── relauncher/
│ │ │ │ └── browser/
│ │ │ │ └── relauncher.contribution.ts
│ │ │ ├── remote/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── explorerViewItems.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── remoteViewlet.css
│ │ │ │ │ │ └── tunnelView.css
│ │ │ │ │ ├── remote.contribution.ts
│ │ │ │ │ ├── remote.ts
│ │ │ │ │ ├── remoteConnectionHealth.ts
│ │ │ │ │ ├── remoteExplorer.ts
│ │ │ │ │ ├── remoteIcons.ts
│ │ │ │ │ ├── remoteIndicator.ts
│ │ │ │ │ ├── remoteStartEntry.contribution.ts
│ │ │ │ │ ├── remoteStartEntry.ts
│ │ │ │ │ ├── showCandidate.ts
│ │ │ │ │ ├── tunnelFactory.ts
│ │ │ │ │ ├── tunnelView.ts
│ │ │ │ │ └── urlFinder.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── remote.contribution.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── remote.contribution.ts
│ │ │ ├── remoteTunnel/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── remoteTunnel.contribution.ts
│ │ │ ├── replNotebook/
│ │ │ │ └── browser/
│ │ │ │ ├── interactiveEditor.css
│ │ │ │ ├── media/
│ │ │ │ │ └── interactive.css
│ │ │ │ ├── repl.contribution.ts
│ │ │ │ ├── replEditor.ts
│ │ │ │ ├── replEditorAccessibilityHelp.ts
│ │ │ │ └── replEditorInput.ts
│ │ │ ├── sash/
│ │ │ │ └── browser/
│ │ │ │ ├── sash.contribution.ts
│ │ │ │ └── sash.ts
│ │ │ ├── scm/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── activity.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── dirtydiffDecorator.css
│ │ │ │ │ │ └── scm.css
│ │ │ │ │ ├── menus.ts
│ │ │ │ │ ├── quickDiffDecorator.ts
│ │ │ │ │ ├── quickDiffModel.ts
│ │ │ │ │ ├── quickDiffWidget.ts
│ │ │ │ │ ├── scm.contribution.ts
│ │ │ │ │ ├── scmAccessibilityHelp.ts
│ │ │ │ │ ├── scmHistory.ts
│ │ │ │ │ ├── scmHistoryViewPane.ts
│ │ │ │ │ ├── scmRepositoriesViewPane.ts
│ │ │ │ │ ├── scmRepositoryRenderer.ts
│ │ │ │ │ ├── scmViewPane.ts
│ │ │ │ │ ├── scmViewPaneContainer.ts
│ │ │ │ │ ├── scmViewService.ts
│ │ │ │ │ ├── util.ts
│ │ │ │ │ └── workingSet.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── history.ts
│ │ │ │ │ ├── quickDiff.ts
│ │ │ │ │ ├── quickDiffService.ts
│ │ │ │ │ ├── scm.ts
│ │ │ │ │ └── scmService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── scmHistory.test.ts
│ │ │ ├── scrollLocking/
│ │ │ │ └── browser/
│ │ │ │ ├── scrollLocking.contribution.ts
│ │ │ │ └── scrollLocking.ts
│ │ │ ├── search/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── AISearch/
│ │ │ │ │ │ ├── aiSearchModel.ts
│ │ │ │ │ │ └── aiSearchModelBase.ts
│ │ │ │ │ ├── anythingQuickAccess.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── anythingQuickAccess.css
│ │ │ │ │ │ └── searchview.css
│ │ │ │ │ ├── notebookSearch/
│ │ │ │ │ │ ├── notebookSearchContributions.ts
│ │ │ │ │ │ ├── notebookSearchModel.ts
│ │ │ │ │ │ ├── notebookSearchModelBase.ts
│ │ │ │ │ │ ├── notebookSearchService.ts
│ │ │ │ │ │ └── searchNotebookHelpers.ts
│ │ │ │ │ ├── patternInputWidget.ts
│ │ │ │ │ ├── quickTextSearch/
│ │ │ │ │ │ └── textSearchQuickAccess.ts
│ │ │ │ │ ├── replace.ts
│ │ │ │ │ ├── replaceContributions.ts
│ │ │ │ │ ├── replaceService.ts
│ │ │ │ │ ├── search.contribution.ts
│ │ │ │ │ ├── searchActionsBase.ts
│ │ │ │ │ ├── searchActionsCopy.ts
│ │ │ │ │ ├── searchActionsFind.ts
│ │ │ │ │ ├── searchActionsNav.ts
│ │ │ │ │ ├── searchActionsRemoveReplace.ts
│ │ │ │ │ ├── searchActionsSymbol.ts
│ │ │ │ │ ├── searchActionsTextQuickAccess.ts
│ │ │ │ │ ├── searchActionsTopBar.ts
│ │ │ │ │ ├── searchCompare.ts
│ │ │ │ │ ├── searchFindInput.ts
│ │ │ │ │ ├── searchIcons.ts
│ │ │ │ │ ├── searchMessage.ts
│ │ │ │ │ ├── searchResultsView.ts
│ │ │ │ │ ├── searchTreeModel/
│ │ │ │ │ │ ├── fileMatch.ts
│ │ │ │ │ │ ├── folderMatch.ts
│ │ │ │ │ │ ├── match.ts
│ │ │ │ │ │ ├── rangeDecorations.ts
│ │ │ │ │ │ ├── searchModel.ts
│ │ │ │ │ │ ├── searchResult.ts
│ │ │ │ │ │ ├── searchTreeCommon.ts
│ │ │ │ │ │ ├── searchViewModelWorkbenchService.ts
│ │ │ │ │ │ └── textSearchHeading.ts
│ │ │ │ │ ├── searchView.ts
│ │ │ │ │ ├── searchWidget.ts
│ │ │ │ │ └── symbolsQuickAccess.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── cacheState.ts
│ │ │ │ │ ├── cellSearchModel.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── notebookSearch.ts
│ │ │ │ │ ├── search.ts
│ │ │ │ │ ├── searchHistoryService.ts
│ │ │ │ │ └── searchNotebookHelpers.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── mockSearchTree.ts
│ │ │ │ │ ├── searchActions.test.ts
│ │ │ │ │ ├── searchModel.test.ts
│ │ │ │ │ ├── searchNotebookHelpers.test.ts
│ │ │ │ │ ├── searchResult.test.ts
│ │ │ │ │ ├── searchTestCommon.ts
│ │ │ │ │ └── searchViewlet.test.ts
│ │ │ │ └── common/
│ │ │ │ ├── cacheState.test.ts
│ │ │ │ └── extractRange.test.ts
│ │ │ ├── searchEditor/
│ │ │ │ └── browser/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── media/
│ │ │ │ │ └── searchEditor.css
│ │ │ │ ├── searchEditor.contribution.ts
│ │ │ │ ├── searchEditor.ts
│ │ │ │ ├── searchEditorActions.ts
│ │ │ │ ├── searchEditorInput.ts
│ │ │ │ ├── searchEditorModel.ts
│ │ │ │ └── searchEditorSerialization.ts
│ │ │ ├── share/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── share.contribution.ts
│ │ │ │ │ ├── share.css
│ │ │ │ │ └── shareService.ts
│ │ │ │ └── common/
│ │ │ │ └── share.ts
│ │ │ ├── snippets/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── commands/
│ │ │ │ │ │ ├── abstractSnippetsActions.ts
│ │ │ │ │ │ ├── configureSnippets.ts
│ │ │ │ │ │ ├── fileTemplateSnippets.ts
│ │ │ │ │ │ ├── insertSnippet.ts
│ │ │ │ │ │ └── surroundWithSnippet.ts
│ │ │ │ │ ├── snippetCodeActionProvider.ts
│ │ │ │ │ ├── snippetCompletionProvider.ts
│ │ │ │ │ ├── snippetPicker.ts
│ │ │ │ │ ├── snippets.contribution.ts
│ │ │ │ │ ├── snippets.ts
│ │ │ │ │ ├── snippetsFile.ts
│ │ │ │ │ ├── snippetsService.ts
│ │ │ │ │ └── tabCompletion.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── snippetFile.test.ts
│ │ │ │ ├── snippetsRegistry.test.ts
│ │ │ │ ├── snippetsRewrite.test.ts
│ │ │ │ └── snippetsService.test.ts
│ │ │ ├── speech/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── speech.contribution.ts
│ │ │ │ │ ├── speechAccessibilitySignal.ts
│ │ │ │ │ └── speechService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── speechService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── speechService.test.ts
│ │ │ ├── splash/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── partsSplash.ts
│ │ │ │ │ ├── splash.contribution.ts
│ │ │ │ │ └── splash.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── splash.contribution.ts
│ │ │ ├── surveys/
│ │ │ │ └── browser/
│ │ │ │ ├── languageSurveys.contribution.ts
│ │ │ │ └── nps.contribution.ts
│ │ │ ├── tags/
│ │ │ │ ├── browser/
│ │ │ │ │ └── workspaceTagsService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── javaWorkspaceTags.ts
│ │ │ │ │ └── workspaceTags.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── tags.contribution.ts
│ │ │ │ │ ├── workspaceTags.ts
│ │ │ │ │ └── workspaceTagsService.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ └── workspaceTags.test.ts
│ │ │ ├── tasks/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── abstractTaskService.ts
│ │ │ │ │ ├── runAutomaticTasks.ts
│ │ │ │ │ ├── task.contribution.ts
│ │ │ │ │ ├── taskQuickPick.ts
│ │ │ │ │ ├── taskService.ts
│ │ │ │ │ ├── taskTerminalStatus.ts
│ │ │ │ │ ├── tasksQuickAccess.ts
│ │ │ │ │ └── terminalTaskSystem.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── jsonSchemaCommon.ts
│ │ │ │ │ ├── jsonSchema_v1.ts
│ │ │ │ │ ├── jsonSchema_v2.ts
│ │ │ │ │ ├── problemCollectors.ts
│ │ │ │ │ ├── problemMatcher.ts
│ │ │ │ │ ├── taskConfiguration.ts
│ │ │ │ │ ├── taskDefinitionRegistry.ts
│ │ │ │ │ ├── taskService.ts
│ │ │ │ │ ├── taskSystem.ts
│ │ │ │ │ ├── taskTemplates.ts
│ │ │ │ │ └── tasks.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── taskService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ └── taskTerminalStatus.test.ts
│ │ │ │ └── common/
│ │ │ │ ├── problemMatcher.test.ts
│ │ │ │ └── taskConfiguration.test.ts
│ │ │ ├── telemetry/
│ │ │ │ └── browser/
│ │ │ │ └── telemetry.contribution.ts
│ │ │ ├── terminal/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── baseTerminalBackend.ts
│ │ │ │ │ ├── detachedTerminal.ts
│ │ │ │ │ ├── environmentVariableInfo.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── terminal.css
│ │ │ │ │ │ ├── terminalVoice.css
│ │ │ │ │ │ ├── widgets.css
│ │ │ │ │ │ └── xterm.css
│ │ │ │ │ ├── remotePty.ts
│ │ │ │ │ ├── remoteTerminalBackend.ts
│ │ │ │ │ ├── terminal.contribution.ts
│ │ │ │ │ ├── terminal.ts
│ │ │ │ │ ├── terminal.web.contribution.ts
│ │ │ │ │ ├── terminalActions.ts
│ │ │ │ │ ├── terminalCommands.ts
│ │ │ │ │ ├── terminalConfigurationService.ts
│ │ │ │ │ ├── terminalContextMenu.ts
│ │ │ │ │ ├── terminalEditor.ts
│ │ │ │ │ ├── terminalEditorInput.ts
│ │ │ │ │ ├── terminalEditorSerializer.ts
│ │ │ │ │ ├── terminalEditorService.ts
│ │ │ │ │ ├── terminalEscapeSequences.ts
│ │ │ │ │ ├── terminalEvents.ts
│ │ │ │ │ ├── terminalExtensions.ts
│ │ │ │ │ ├── terminalGroup.ts
│ │ │ │ │ ├── terminalGroupService.ts
│ │ │ │ │ ├── terminalIcon.ts
│ │ │ │ │ ├── terminalIconPicker.ts
│ │ │ │ │ ├── terminalIcons.ts
│ │ │ │ │ ├── terminalInstance.ts
│ │ │ │ │ ├── terminalInstanceService.ts
│ │ │ │ │ ├── terminalKeybindings.ts
│ │ │ │ │ ├── terminalMainContribution.ts
│ │ │ │ │ ├── terminalMenus.ts
│ │ │ │ │ ├── terminalProcessExtHostProxy.ts
│ │ │ │ │ ├── terminalProcessManager.ts
│ │ │ │ │ ├── terminalProfileQuickpick.ts
│ │ │ │ │ ├── terminalProfileResolverService.ts
│ │ │ │ │ ├── terminalProfileService.ts
│ │ │ │ │ ├── terminalResizeDebouncer.ts
│ │ │ │ │ ├── terminalService.ts
│ │ │ │ │ ├── terminalStatusList.ts
│ │ │ │ │ ├── terminalTabbedView.ts
│ │ │ │ │ ├── terminalTabsList.ts
│ │ │ │ │ ├── terminalTelemetry.ts
│ │ │ │ │ ├── terminalTestHelpers.ts
│ │ │ │ │ ├── terminalTooltip.ts
│ │ │ │ │ ├── terminalUri.ts
│ │ │ │ │ ├── terminalView.ts
│ │ │ │ │ ├── widgets/
│ │ │ │ │ │ ├── terminalHoverWidget.ts
│ │ │ │ │ │ ├── widgetManager.ts
│ │ │ │ │ │ └── widgets.ts
│ │ │ │ │ ├── xterm/
│ │ │ │ │ │ ├── decorationAddon.ts
│ │ │ │ │ │ ├── decorationStyles.ts
│ │ │ │ │ │ ├── lineDataEventAddon.ts
│ │ │ │ │ │ ├── markNavigationAddon.ts
│ │ │ │ │ │ ├── xtermAddonImporter.ts
│ │ │ │ │ │ └── xtermTerminal.ts
│ │ │ │ │ └── xterm-private.d.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── basePty.ts
│ │ │ │ │ ├── environmentVariable.contribution.ts
│ │ │ │ │ ├── environmentVariable.ts
│ │ │ │ │ ├── environmentVariableService.ts
│ │ │ │ │ ├── remote/
│ │ │ │ │ │ ├── remoteTerminalChannel.ts
│ │ │ │ │ │ └── terminal.ts
│ │ │ │ │ ├── scripts/
│ │ │ │ │ │ ├── cgmanifest.json
│ │ │ │ │ │ ├── shellIntegration-bash.sh
│ │ │ │ │ │ ├── shellIntegration-env.zsh
│ │ │ │ │ │ ├── shellIntegration-login.zsh
│ │ │ │ │ │ ├── shellIntegration-profile.zsh
│ │ │ │ │ │ ├── shellIntegration-rc.zsh
│ │ │ │ │ │ ├── shellIntegration.fish
│ │ │ │ │ │ └── shellIntegration.ps1
│ │ │ │ │ ├── terminal.ts
│ │ │ │ │ ├── terminalColorRegistry.ts
│ │ │ │ │ ├── terminalConfiguration.ts
│ │ │ │ │ ├── terminalContextKey.ts
│ │ │ │ │ ├── terminalEnvironment.ts
│ │ │ │ │ ├── terminalExtensionPoints.contribution.ts
│ │ │ │ │ ├── terminalExtensionPoints.ts
│ │ │ │ │ ├── terminalStorageKeys.ts
│ │ │ │ │ └── terminalStrings.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── localPty.ts
│ │ │ │ │ ├── localTerminalBackend.ts
│ │ │ │ │ ├── terminal.contribution.ts
│ │ │ │ │ ├── terminalNativeContribution.ts
│ │ │ │ │ ├── terminalProfileResolverService.ts
│ │ │ │ │ └── terminalRemote.ts
│ │ │ │ ├── terminal.all.ts
│ │ │ │ ├── terminalContribChatExports.ts
│ │ │ │ ├── terminalContribExports.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── capabilities/
│ │ │ │ │ │ ├── commandDetectionCapability.test.ts
│ │ │ │ │ │ ├── partialCommandDetectionCapability.test.ts
│ │ │ │ │ │ └── terminalCapabilityStore.test.ts
│ │ │ │ │ ├── terminalActions.test.ts
│ │ │ │ │ ├── terminalConfigurationService.test.ts
│ │ │ │ │ ├── terminalInstance.test.ts
│ │ │ │ │ ├── terminalInstanceService.test.ts
│ │ │ │ │ ├── terminalProcessManager.test.ts
│ │ │ │ │ ├── terminalProfileService.integrationTest.ts
│ │ │ │ │ ├── terminalService.test.ts
│ │ │ │ │ ├── terminalStatusList.test.ts
│ │ │ │ │ ├── terminalUri.test.ts
│ │ │ │ │ └── xterm/
│ │ │ │ │ ├── decorationAddon.test.ts
│ │ │ │ │ ├── lineDataEventAddon.test.ts
│ │ │ │ │ ├── shellIntegrationAddon.test.ts
│ │ │ │ │ └── xtermTerminal.test.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── environmentVariableCollection.test.ts
│ │ │ │ │ ├── environmentVariableService.test.ts
│ │ │ │ │ ├── environmentVariableShared.test.ts
│ │ │ │ │ ├── terminalColorRegistry.test.ts
│ │ │ │ │ ├── terminalDataBuffering.test.ts
│ │ │ │ │ └── terminalEnvironment.test.ts
│ │ │ │ └── node/
│ │ │ │ └── terminalProfiles.test.ts
│ │ │ ├── terminalContrib/
│ │ │ │ ├── README.md
│ │ │ │ ├── accessibility/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── bufferContentTracker.ts
│ │ │ │ │ │ ├── terminal.accessibility.contribution.ts
│ │ │ │ │ │ ├── terminalAccessibilityHelp.ts
│ │ │ │ │ │ ├── terminalAccessibleBufferProvider.ts
│ │ │ │ │ │ └── textAreaSyncAddon.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── terminal.accessibility.ts
│ │ │ │ │ │ └── terminalAccessibilityConfiguration.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── bufferContentTracker.test.ts
│ │ │ │ ├── autoReplies/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── terminal.autoReplies.contribution.ts
│ │ │ │ │ └── common/
│ │ │ │ │ └── terminalAutoRepliesConfiguration.ts
│ │ │ │ ├── chat/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ ├── terminalChatWidget.css
│ │ │ │ │ │ │ └── terminalInitialHint.css
│ │ │ │ │ │ ├── terminal.chat.contribution.ts
│ │ │ │ │ │ ├── terminal.initialHint.contribution.ts
│ │ │ │ │ │ ├── terminalChat.ts
│ │ │ │ │ │ ├── terminalChatAccessibilityHelp.ts
│ │ │ │ │ │ ├── terminalChatAccessibleView.ts
│ │ │ │ │ │ ├── terminalChatActions.ts
│ │ │ │ │ │ ├── terminalChatController.ts
│ │ │ │ │ │ ├── terminalChatEnabler.ts
│ │ │ │ │ │ └── terminalChatWidget.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ └── terminalInitialHintConfiguration.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── terminalInitialHint.test.ts
│ │ │ │ ├── clipboard/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── terminal.clipboard.contribution.ts
│ │ │ │ │ │ └── terminalClipboard.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── terminalClipboard.test.ts
│ │ │ │ ├── commandGuide/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── terminal.commandGuide.contribution.ts
│ │ │ │ │ └── common/
│ │ │ │ │ └── terminalCommandGuideConfiguration.ts
│ │ │ │ ├── developer/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── developer.css
│ │ │ │ │ │ └── terminal.developer.contribution.ts
│ │ │ │ │ └── common/
│ │ │ │ │ └── terminal.developer.ts
│ │ │ │ ├── environmentChanges/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── terminal.environmentChanges.contribution.ts
│ │ │ │ ├── find/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── terminalFind.css
│ │ │ │ │ │ ├── terminal.find.contribution.ts
│ │ │ │ │ │ └── terminalFindWidget.ts
│ │ │ │ │ └── common/
│ │ │ │ │ └── terminal.find.ts
│ │ │ │ ├── history/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── terminal.history.contribution.ts
│ │ │ │ │ │ └── terminalRunRecentQuickPick.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── history.ts
│ │ │ │ │ │ └── terminal.history.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── common/
│ │ │ │ │ └── history.test.ts
│ │ │ │ ├── links/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── links.ts
│ │ │ │ │ │ ├── terminal.links.contribution.ts
│ │ │ │ │ │ ├── terminalExternalLinkDetector.ts
│ │ │ │ │ │ ├── terminalLink.ts
│ │ │ │ │ │ ├── terminalLinkDetectorAdapter.ts
│ │ │ │ │ │ ├── terminalLinkHelpers.ts
│ │ │ │ │ │ ├── terminalLinkManager.ts
│ │ │ │ │ │ ├── terminalLinkOpeners.ts
│ │ │ │ │ │ ├── terminalLinkParsing.ts
│ │ │ │ │ │ ├── terminalLinkProviderService.ts
│ │ │ │ │ │ ├── terminalLinkQuickpick.ts
│ │ │ │ │ │ ├── terminalLinkResolver.ts
│ │ │ │ │ │ ├── terminalLocalLinkDetector.ts
│ │ │ │ │ │ ├── terminalMultiLineLinkDetector.ts
│ │ │ │ │ │ ├── terminalUriLinkDetector.ts
│ │ │ │ │ │ └── terminalWordLinkDetector.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ └── terminal.links.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── linkTestUtils.ts
│ │ │ │ │ ├── terminalLinkHelpers.test.ts
│ │ │ │ │ ├── terminalLinkManager.test.ts
│ │ │ │ │ ├── terminalLinkOpeners.test.ts
│ │ │ │ │ ├── terminalLinkParsing.test.ts
│ │ │ │ │ ├── terminalLocalLinkDetector.test.ts
│ │ │ │ │ ├── terminalMultiLineLinkDetector.test.ts
│ │ │ │ │ ├── terminalUriLinkDetector.test.ts
│ │ │ │ │ └── terminalWordLinkDetector.test.ts
│ │ │ │ ├── quickAccess/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── terminal.quickAccess.contribution.ts
│ │ │ │ │ └── terminalQuickAccess.ts
│ │ │ │ ├── quickFix/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── terminalQuickFix.css
│ │ │ │ │ │ ├── quickFix.ts
│ │ │ │ │ │ ├── quickFixAddon.ts
│ │ │ │ │ │ ├── terminal.quickFix.contribution.ts
│ │ │ │ │ │ ├── terminalQuickFixBuiltinActions.ts
│ │ │ │ │ │ └── terminalQuickFixService.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── quickFixAddon.test.ts
│ │ │ │ ├── stickyScroll/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── stickyScroll.css
│ │ │ │ │ │ ├── terminal.stickyScroll.contribution.ts
│ │ │ │ │ │ ├── terminalStickyScrollColorRegistry.ts
│ │ │ │ │ │ ├── terminalStickyScrollContribution.ts
│ │ │ │ │ │ └── terminalStickyScrollOverlay.ts
│ │ │ │ │ └── common/
│ │ │ │ │ └── terminalStickyScrollConfiguration.ts
│ │ │ │ ├── suggest/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ └── terminalSymbolIcons.css
│ │ │ │ │ │ ├── pwshCompletionProviderAddon.ts
│ │ │ │ │ │ ├── terminal.suggest.contribution.ts
│ │ │ │ │ │ ├── terminalCompletionItem.ts
│ │ │ │ │ │ ├── terminalCompletionModel.ts
│ │ │ │ │ │ ├── terminalCompletionService.ts
│ │ │ │ │ │ ├── terminalSuggestAddon.ts
│ │ │ │ │ │ ├── terminalSuggestTelemetry.ts
│ │ │ │ │ │ └── terminalSymbolIcons.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── terminal.suggest.ts
│ │ │ │ │ │ └── terminalSuggestConfiguration.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ ├── terminalCompletionModel.test.ts
│ │ │ │ │ └── terminalCompletionService.test.ts
│ │ │ │ ├── typeAhead/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── terminal.typeAhead.contribution.ts
│ │ │ │ │ │ └── terminalTypeAheadAddon.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ └── terminalTypeAheadConfiguration.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── terminalTypeAhead.test.ts
│ │ │ │ ├── wslRecommendation/
│ │ │ │ │ └── browser/
│ │ │ │ │ └── terminal.wslRecommendation.contribution.ts
│ │ │ │ └── zoom/
│ │ │ │ ├── browser/
│ │ │ │ │ └── terminal.zoom.contribution.ts
│ │ │ │ └── common/
│ │ │ │ └── terminal.zoom.ts
│ │ │ ├── testing/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── codeCoverageDecorations.ts
│ │ │ │ │ ├── codeCoverageDisplayUtils.ts
│ │ │ │ │ ├── explorerProjections/
│ │ │ │ │ │ ├── display.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── listProjection.ts
│ │ │ │ │ │ ├── testItemContextOverlay.ts
│ │ │ │ │ │ ├── testingObjectTree.ts
│ │ │ │ │ │ ├── testingViewState.ts
│ │ │ │ │ │ └── treeProjection.ts
│ │ │ │ │ ├── icons.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ ├── testMessageColorizer.css
│ │ │ │ │ │ └── testing.css
│ │ │ │ │ ├── testCoverageBars.ts
│ │ │ │ │ ├── testCoverageView.ts
│ │ │ │ │ ├── testExplorerActions.ts
│ │ │ │ │ ├── testMessageColorizer.ts
│ │ │ │ │ ├── testResultsView/
│ │ │ │ │ │ ├── testResultsOutput.ts
│ │ │ │ │ │ ├── testResultsSubject.ts
│ │ │ │ │ │ ├── testResultsTree.ts
│ │ │ │ │ │ ├── testResultsViewContent.css
│ │ │ │ │ │ └── testResultsViewContent.ts
│ │ │ │ │ ├── testing.contribution.ts
│ │ │ │ │ ├── testingConfigurationUi.ts
│ │ │ │ │ ├── testingDecorations.ts
│ │ │ │ │ ├── testingExplorerFilter.ts
│ │ │ │ │ ├── testingExplorerView.ts
│ │ │ │ │ ├── testingOutputPeek.ts
│ │ │ │ │ ├── testingProgressUiService.ts
│ │ │ │ │ ├── testingViewPaneContainer.ts
│ │ │ │ │ └── theme.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── configuration.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── getComputedState.ts
│ │ │ │ │ ├── mainThreadTestCollection.ts
│ │ │ │ │ ├── observableUtils.ts
│ │ │ │ │ ├── observableValue.ts
│ │ │ │ │ ├── storedValue.ts
│ │ │ │ │ ├── testCoverage.ts
│ │ │ │ │ ├── testCoverageService.ts
│ │ │ │ │ ├── testExclusions.ts
│ │ │ │ │ ├── testExplorerFilterState.ts
│ │ │ │ │ ├── testId.ts
│ │ │ │ │ ├── testItemCollection.ts
│ │ │ │ │ ├── testProfileService.ts
│ │ │ │ │ ├── testResult.ts
│ │ │ │ │ ├── testResultService.ts
│ │ │ │ │ ├── testResultStorage.ts
│ │ │ │ │ ├── testService.ts
│ │ │ │ │ ├── testServiceImpl.ts
│ │ │ │ │ ├── testTypes.ts
│ │ │ │ │ ├── testingContentProvider.ts
│ │ │ │ │ ├── testingContextKeys.ts
│ │ │ │ │ ├── testingContinuousRunService.ts
│ │ │ │ │ ├── testingDecorations.ts
│ │ │ │ │ ├── testingPeekOpener.ts
│ │ │ │ │ ├── testingStates.ts
│ │ │ │ │ └── testingUri.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ ├── Code_Coverage_Decorations_CoverageDetailsModel_1.0.snap
│ │ │ │ │ │ ├── Code_Coverage_Decorations_CoverageDetailsModel_2.0.snap
│ │ │ │ │ │ ├── Code_Coverage_Decorations_CoverageDetailsModel_3.0.snap
│ │ │ │ │ │ └── Code_Coverage_Decorations_CoverageDetailsModel_4.0.snap
│ │ │ │ │ ├── codeCoverageDecorations.test.ts
│ │ │ │ │ ├── explorerProjections/
│ │ │ │ │ │ ├── nameProjection.test.ts
│ │ │ │ │ │ └── treeProjection.test.ts
│ │ │ │ │ └── testObjectTree.ts
│ │ │ │ └── common/
│ │ │ │ ├── testCoverage.test.ts
│ │ │ │ ├── testExplorerFilterState.test.ts
│ │ │ │ ├── testProfileService.test.ts
│ │ │ │ ├── testResultService.test.ts
│ │ │ │ ├── testResultStorage.test.ts
│ │ │ │ ├── testService.test.ts
│ │ │ │ ├── testStubs.ts
│ │ │ │ ├── testingContinuousRunService.test.ts
│ │ │ │ └── testingUri.test.ts
│ │ │ ├── themes/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── themes.contribution.ts
│ │ │ │ │ └── themes.test.contribution.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ ├── colorRegistry.releaseTest.ts
│ │ │ │ └── colorRegistryExport.test.ts
│ │ │ ├── timeline/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── timelinePane.css
│ │ │ │ │ ├── timeline.contribution.ts
│ │ │ │ │ └── timelinePane.ts
│ │ │ │ └── common/
│ │ │ │ ├── timeline.ts
│ │ │ │ └── timelineService.ts
│ │ │ ├── typeHierarchy/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── typeHierarchy.css
│ │ │ │ │ ├── typeHierarchy.contribution.ts
│ │ │ │ │ ├── typeHierarchyPeek.ts
│ │ │ │ │ └── typeHierarchyTree.ts
│ │ │ │ └── common/
│ │ │ │ └── typeHierarchy.ts
│ │ │ ├── update/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── releasenoteseditor.css
│ │ │ │ │ ├── releaseNotesEditor.ts
│ │ │ │ │ ├── update.contribution.ts
│ │ │ │ │ └── update.ts
│ │ │ │ └── common/
│ │ │ │ └── update.ts
│ │ │ ├── url/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── externalUriResolver.ts
│ │ │ │ │ ├── trustedDomainService.ts
│ │ │ │ │ ├── trustedDomains.ts
│ │ │ │ │ ├── trustedDomainsFileSystemProvider.ts
│ │ │ │ │ ├── trustedDomainsValidator.ts
│ │ │ │ │ └── url.contribution.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── trustedDomains.ts
│ │ │ │ │ └── urlGlob.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── mockTrustedDomainService.ts
│ │ │ │ └── trustedDomains.test.ts
│ │ │ ├── userDataProfile/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── userDataProfilesEditor.css
│ │ │ │ │ ├── userDataProfile.contribution.ts
│ │ │ │ │ ├── userDataProfile.ts
│ │ │ │ │ ├── userDataProfileActions.ts
│ │ │ │ │ ├── userDataProfilesEditor.ts
│ │ │ │ │ └── userDataProfilesEditorModel.ts
│ │ │ │ └── common/
│ │ │ │ └── userDataProfile.ts
│ │ │ ├── userDataSync/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── userDataSync.contribution.ts
│ │ │ │ │ ├── userDataSync.ts
│ │ │ │ │ ├── userDataSyncConflictsView.ts
│ │ │ │ │ ├── userDataSyncTrigger.ts
│ │ │ │ │ └── userDataSyncViews.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── userDataSync.contribution.ts
│ │ │ ├── void/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── _dummyContrib.ts
│ │ │ │ │ ├── _markerCheckService.ts
│ │ │ │ │ ├── actionIDs.ts
│ │ │ │ │ ├── aiRegexService.ts
│ │ │ │ │ ├── autocompleteService.ts
│ │ │ │ │ ├── chatThreadService.ts
│ │ │ │ │ ├── contextGatheringService.ts
│ │ │ │ │ ├── convertToLLMMessageService.ts
│ │ │ │ │ ├── convertToLLMMessageWorkbenchContrib.ts
│ │ │ │ │ ├── editCodeService.ts
│ │ │ │ │ ├── editCodeServiceInterface.ts
│ │ │ │ │ ├── extensionTransferService.ts
│ │ │ │ │ ├── extensionTransferTypes.ts
│ │ │ │ │ ├── fileService.ts
│ │ │ │ │ ├── helperServices/
│ │ │ │ │ │ └── consistentItemService.ts
│ │ │ │ │ ├── helpers/
│ │ │ │ │ │ └── findDiffs.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── void.css
│ │ │ │ │ ├── metricsPollService.ts
│ │ │ │ │ ├── miscWokrbenchContrib.ts
│ │ │ │ │ ├── quickEditActions.ts
│ │ │ │ │ ├── react/
│ │ │ │ │ │ ├── .gitignore
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ ├── build.js
│ │ │ │ │ │ ├── src/
│ │ │ │ │ │ │ ├── diff/
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ ├── markdown/
│ │ │ │ │ │ │ │ ├── ApplyBlockHoverButtons.tsx
│ │ │ │ │ │ │ │ └── ChatMarkdownRender.tsx
│ │ │ │ │ │ │ ├── quick-edit-tsx/
│ │ │ │ │ │ │ │ ├── QuickEdit.tsx
│ │ │ │ │ │ │ │ ├── QuickEditChat.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ ├── sidebar-tsx/
│ │ │ │ │ │ │ │ ├── ErrorBoundary.tsx
│ │ │ │ │ │ │ │ ├── ErrorDisplay.tsx
│ │ │ │ │ │ │ │ ├── Sidebar.tsx
│ │ │ │ │ │ │ │ ├── SidebarChat.tsx
│ │ │ │ │ │ │ │ ├── SidebarThreadSelector.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ ├── styles.css
│ │ │ │ │ │ │ ├── util/
│ │ │ │ │ │ │ │ ├── helpers.tsx
│ │ │ │ │ │ │ │ ├── inputs.tsx
│ │ │ │ │ │ │ │ ├── mountFnGenerator.tsx
│ │ │ │ │ │ │ │ ├── services.tsx
│ │ │ │ │ │ │ │ └── useScrollbarStyles.tsx
│ │ │ │ │ │ │ ├── void-editor-widgets-tsx/
│ │ │ │ │ │ │ │ ├── VoidCommandBar.tsx
│ │ │ │ │ │ │ │ ├── VoidSelectionHelper.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ ├── void-onboarding/
│ │ │ │ │ │ │ │ ├── VoidOnboarding.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ ├── void-settings-tsx/
│ │ │ │ │ │ │ │ ├── ModelDropdown.tsx
│ │ │ │ │ │ │ │ ├── Settings.tsx
│ │ │ │ │ │ │ │ ├── WarningBox.tsx
│ │ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ │ └── void-tooltip/
│ │ │ │ │ │ │ ├── VoidTooltip.tsx
│ │ │ │ │ │ │ └── index.tsx
│ │ │ │ │ │ ├── tailwind.config.js
│ │ │ │ │ │ ├── tsconfig.json
│ │ │ │ │ │ └── tsup.config.js
│ │ │ │ │ ├── sidebarActions.ts
│ │ │ │ │ ├── sidebarPane.ts
│ │ │ │ │ ├── terminalToolService.ts
│ │ │ │ │ ├── toolsService.ts
│ │ │ │ │ ├── tooltipService.ts
│ │ │ │ │ ├── void.contribution.ts
│ │ │ │ │ ├── voidCommandBarService.ts
│ │ │ │ │ ├── voidOnboardingService.ts
│ │ │ │ │ ├── voidSCMService.ts
│ │ │ │ │ ├── voidSelectionHelperWidget.ts
│ │ │ │ │ ├── voidSettingsPane.ts
│ │ │ │ │ └── voidUpdateActions.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── chatThreadServiceTypes.ts
│ │ │ │ │ ├── directoryStrService.ts
│ │ │ │ │ ├── directoryStrTypes.ts
│ │ │ │ │ ├── editCodeServiceTypes.ts
│ │ │ │ │ ├── helpers/
│ │ │ │ │ │ ├── colors.ts
│ │ │ │ │ │ ├── extractCodeFromResult.ts
│ │ │ │ │ │ ├── languageHelpers.ts
│ │ │ │ │ │ ├── systemInfo.ts
│ │ │ │ │ │ └── util.ts
│ │ │ │ │ ├── mcpService.ts
│ │ │ │ │ ├── mcpServiceTypes.ts
│ │ │ │ │ ├── metricsService.ts
│ │ │ │ │ ├── modelCapabilities.ts
│ │ │ │ │ ├── prompt/
│ │ │ │ │ │ └── prompts.ts
│ │ │ │ │ ├── refreshModelService.ts
│ │ │ │ │ ├── sendLLMMessageService.ts
│ │ │ │ │ ├── sendLLMMessageTypes.ts
│ │ │ │ │ ├── storageKeys.ts
│ │ │ │ │ ├── toolsServiceTypes.ts
│ │ │ │ │ ├── voidModelService.ts
│ │ │ │ │ ├── voidSCMTypes.ts
│ │ │ │ │ ├── voidSettingsService.ts
│ │ │ │ │ ├── voidSettingsTypes.ts
│ │ │ │ │ ├── voidUpdateService.ts
│ │ │ │ │ └── voidUpdateServiceTypes.ts
│ │ │ │ └── electron-main/
│ │ │ │ ├── llmMessage/
│ │ │ │ │ ├── extractGrammar.ts
│ │ │ │ │ ├── sendLLMMessage.impl.ts
│ │ │ │ │ └── sendLLMMessage.ts
│ │ │ │ ├── mcpChannel.ts
│ │ │ │ ├── metricsMainService.ts
│ │ │ │ ├── sendLLMMessageChannel.ts
│ │ │ │ ├── voidSCMMainService.ts
│ │ │ │ └── voidUpdateMainService.ts
│ │ │ ├── webview/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── overlayWebview.ts
│ │ │ │ │ ├── pre/
│ │ │ │ │ │ ├── fake.html
│ │ │ │ │ │ ├── index-no-csp.html
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── service-worker.js
│ │ │ │ │ ├── resourceLoading.ts
│ │ │ │ │ ├── themeing.ts
│ │ │ │ │ ├── webview.contribution.ts
│ │ │ │ │ ├── webview.ts
│ │ │ │ │ ├── webview.web.contribution.ts
│ │ │ │ │ ├── webviewElement.ts
│ │ │ │ │ ├── webviewFindWidget.ts
│ │ │ │ │ ├── webviewMessages.d.ts
│ │ │ │ │ ├── webviewService.ts
│ │ │ │ │ └── webviewWindowDragMonitor.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── webview.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── webview.contribution.ts
│ │ │ │ ├── webviewCommands.ts
│ │ │ │ ├── webviewElement.ts
│ │ │ │ ├── webviewService.ts
│ │ │ │ └── windowIgnoreMenuShortcutsManager.ts
│ │ │ ├── webviewPanel/
│ │ │ │ └── browser/
│ │ │ │ ├── webviewCommands.ts
│ │ │ │ ├── webviewEditor.ts
│ │ │ │ ├── webviewEditorInput.ts
│ │ │ │ ├── webviewEditorInputSerializer.ts
│ │ │ │ ├── webviewIconManager.ts
│ │ │ │ ├── webviewPanel.contribution.ts
│ │ │ │ └── webviewWorkbenchService.ts
│ │ │ ├── webviewView/
│ │ │ │ └── browser/
│ │ │ │ ├── webviewView.contribution.ts
│ │ │ │ ├── webviewViewPane.ts
│ │ │ │ └── webviewViewService.ts
│ │ │ ├── welcomeBanner/
│ │ │ │ └── browser/
│ │ │ │ └── welcomeBanner.contribution.ts
│ │ │ ├── welcomeDialog/
│ │ │ │ └── browser/
│ │ │ │ ├── media/
│ │ │ │ │ └── welcomeWidget.css
│ │ │ │ ├── welcomeDialog.contribution.ts
│ │ │ │ └── welcomeWidget.ts
│ │ │ ├── welcomeGettingStarted/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── gettingStarted.contribution.ts
│ │ │ │ │ ├── gettingStarted.ts
│ │ │ │ │ ├── gettingStartedAccessibleView.ts
│ │ │ │ │ ├── gettingStartedColors.ts
│ │ │ │ │ ├── gettingStartedDetailsRenderer.ts
│ │ │ │ │ ├── gettingStartedExtensionPoint.ts
│ │ │ │ │ ├── gettingStartedIcons.ts
│ │ │ │ │ ├── gettingStartedInput.ts
│ │ │ │ │ ├── gettingStartedList.ts
│ │ │ │ │ ├── gettingStartedService.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── gettingStarted.css
│ │ │ │ │ └── startupPage.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── gettingStartedContent.ts
│ │ │ │ │ └── media/
│ │ │ │ │ ├── empty.ts
│ │ │ │ │ ├── notebookProfile.ts
│ │ │ │ │ └── theme_picker.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── gettingStartedMarkdownRenderer.test.ts
│ │ │ ├── welcomeViews/
│ │ │ │ └── common/
│ │ │ │ ├── newFile.contribution.ts
│ │ │ │ ├── viewsWelcome.contribution.ts
│ │ │ │ ├── viewsWelcomeContribution.ts
│ │ │ │ └── viewsWelcomeExtensionPoint.ts
│ │ │ ├── welcomeWalkthrough/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── editor/
│ │ │ │ │ │ ├── editorWalkThrough.ts
│ │ │ │ │ │ └── vs_code_editor_walkthrough.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── walkThroughPart.css
│ │ │ │ │ ├── walkThrough.contribution.ts
│ │ │ │ │ ├── walkThroughActions.ts
│ │ │ │ │ ├── walkThroughInput.ts
│ │ │ │ │ └── walkThroughPart.ts
│ │ │ │ └── common/
│ │ │ │ ├── walkThroughContentProvider.ts
│ │ │ │ └── walkThroughUtils.ts
│ │ │ ├── workspace/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── workspaceTrustEditor.css
│ │ │ │ │ ├── workspace.contribution.ts
│ │ │ │ │ └── workspaceTrustEditor.ts
│ │ │ │ └── common/
│ │ │ │ └── workspace.ts
│ │ │ └── workspaces/
│ │ │ └── browser/
│ │ │ └── workspaces.contribution.ts
│ │ ├── electron-sandbox/
│ │ │ ├── actions/
│ │ │ │ ├── developerActions.ts
│ │ │ │ ├── installActions.ts
│ │ │ │ ├── media/
│ │ │ │ │ └── actions.css
│ │ │ │ └── windowActions.ts
│ │ │ ├── desktop.contribution.ts
│ │ │ ├── desktop.main.ts
│ │ │ ├── media/
│ │ │ │ └── window.css
│ │ │ ├── parts/
│ │ │ │ ├── dialogs/
│ │ │ │ │ ├── dialog.contribution.ts
│ │ │ │ │ └── dialogHandler.ts
│ │ │ │ └── titlebar/
│ │ │ │ ├── menubarControl.ts
│ │ │ │ └── titlebarPart.ts
│ │ │ └── window.ts
│ │ ├── services/
│ │ │ ├── accessibility/
│ │ │ │ ├── common/
│ │ │ │ │ └── accessibleViewInformationService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── accessibilityService.ts
│ │ │ ├── accounts/
│ │ │ │ └── common/
│ │ │ │ └── defaultAccount.ts
│ │ │ ├── actions/
│ │ │ │ └── common/
│ │ │ │ └── menusExtensionPoint.ts
│ │ │ ├── activity/
│ │ │ │ ├── browser/
│ │ │ │ │ └── activityService.ts
│ │ │ │ └── common/
│ │ │ │ └── activity.ts
│ │ │ ├── aiEmbeddingVector/
│ │ │ │ └── common/
│ │ │ │ └── aiEmbeddingVectorService.ts
│ │ │ ├── aiRelatedInformation/
│ │ │ │ ├── common/
│ │ │ │ │ ├── aiRelatedInformation.ts
│ │ │ │ │ └── aiRelatedInformationService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── aiRelatedInformationService.test.ts
│ │ │ ├── assignment/
│ │ │ │ ├── common/
│ │ │ │ │ └── assignmentService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── nullAssignmentService.ts
│ │ │ ├── authentication/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── authenticationAccessService.ts
│ │ │ │ │ ├── authenticationExtensionsService.ts
│ │ │ │ │ ├── authenticationService.ts
│ │ │ │ │ └── authenticationUsageService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── authentication.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── authenticationService.test.ts
│ │ │ ├── auxiliaryWindow/
│ │ │ │ ├── browser/
│ │ │ │ │ └── auxiliaryWindowService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── auxiliaryWindowService.ts
│ │ │ ├── banner/
│ │ │ │ └── browser/
│ │ │ │ └── bannerService.ts
│ │ │ ├── checksum/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── checksumService.ts
│ │ │ ├── clipboard/
│ │ │ │ ├── browser/
│ │ │ │ │ └── clipboardService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── clipboardService.ts
│ │ │ ├── commands/
│ │ │ │ ├── common/
│ │ │ │ │ └── commandService.ts
│ │ │ │ └── test/
│ │ │ │ └── common/
│ │ │ │ └── commandService.test.ts
│ │ │ ├── configuration/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── configuration.ts
│ │ │ │ │ └── configurationService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── configuration.ts
│ │ │ │ │ ├── configurationCache.ts
│ │ │ │ │ ├── configurationEditing.ts
│ │ │ │ │ ├── configurationModels.ts
│ │ │ │ │ ├── jsonEditing.ts
│ │ │ │ │ └── jsonEditingService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── configuration.test.ts
│ │ │ │ │ ├── configurationEditing.test.ts
│ │ │ │ │ └── configurationService.test.ts
│ │ │ │ └── common/
│ │ │ │ ├── configurationModels.test.ts
│ │ │ │ └── testServices.ts
│ │ │ ├── configurationResolver/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── baseConfigurationResolverService.ts
│ │ │ │ │ └── configurationResolverService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── configurationResolver.ts
│ │ │ │ │ ├── configurationResolverExpression.ts
│ │ │ │ │ ├── configurationResolverSchema.ts
│ │ │ │ │ ├── configurationResolverUtils.ts
│ │ │ │ │ └── variableResolver.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── configurationResolverService.ts
│ │ │ │ └── test/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── configurationResolverService.test.ts
│ │ │ ├── contextmenu/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── contextmenuService.ts
│ │ │ ├── decorations/
│ │ │ │ ├── browser/
│ │ │ │ │ └── decorationsService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── decorations.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── decorationsService.test.ts
│ │ │ ├── dialogs/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── abstractFileDialogService.ts
│ │ │ │ │ ├── fileDialogService.ts
│ │ │ │ │ └── simpleFileDialog.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── dialogService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── fileDialogService.ts
│ │ │ │ └── test/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── fileDialogService.test.ts
│ │ │ ├── driver/
│ │ │ │ ├── browser/
│ │ │ │ │ └── driver.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── driver.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── driver.ts
│ │ │ ├── editor/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── codeEditorService.ts
│ │ │ │ │ ├── editorPaneService.ts
│ │ │ │ │ ├── editorResolverService.ts
│ │ │ │ │ └── editorService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── customEditorLabelService.ts
│ │ │ │ │ ├── editorGroupColumn.ts
│ │ │ │ │ ├── editorGroupFinder.ts
│ │ │ │ │ ├── editorGroupsService.ts
│ │ │ │ │ ├── editorPaneService.ts
│ │ │ │ │ ├── editorResolverService.ts
│ │ │ │ │ └── editorService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── customEditorLabelService.test.ts
│ │ │ │ ├── editorGroupsService.test.ts
│ │ │ │ ├── editorResolverService.test.ts
│ │ │ │ ├── editorService.test.ts
│ │ │ │ └── editorsObserver.test.ts
│ │ │ ├── encryption/
│ │ │ │ ├── browser/
│ │ │ │ │ └── encryptionService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── encryptionService.ts
│ │ │ ├── environment/
│ │ │ │ ├── browser/
│ │ │ │ │ └── environmentService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── environmentService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── environmentService.ts
│ │ │ │ └── shellEnvironmentService.ts
│ │ │ ├── extensionManagement/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── builtinExtensionsScannerService.ts
│ │ │ │ │ ├── extensionBisect.ts
│ │ │ │ │ ├── extensionEnablementService.ts
│ │ │ │ │ ├── extensionGalleryManifestService.ts
│ │ │ │ │ ├── extensionsProfileScannerService.ts
│ │ │ │ │ └── webExtensionsScannerService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── extensionFeatures.ts
│ │ │ │ │ ├── extensionFeaturesManagemetService.ts
│ │ │ │ │ ├── extensionGalleryService.ts
│ │ │ │ │ ├── extensionManagement.ts
│ │ │ │ │ ├── extensionManagementChannelClient.ts
│ │ │ │ │ ├── extensionManagementServerService.ts
│ │ │ │ │ ├── extensionManagementService.ts
│ │ │ │ │ ├── extensionsIcons.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── extensionManagement.css
│ │ │ │ │ ├── remoteExtensionManagementService.ts
│ │ │ │ │ └── webExtensionManagementService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── extensionGalleryManifestService.ts
│ │ │ │ │ ├── extensionManagementServerService.ts
│ │ │ │ │ ├── extensionManagementService.ts
│ │ │ │ │ ├── extensionTipsService.ts
│ │ │ │ │ ├── nativeExtensionManagementService.ts
│ │ │ │ │ └── remoteExtensionManagementService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── extensionEnablementService.test.ts
│ │ │ ├── extensionRecommendations/
│ │ │ │ └── common/
│ │ │ │ ├── extensionIgnoredRecommendationsService.ts
│ │ │ │ ├── extensionRecommendations.ts
│ │ │ │ └── workspaceExtensionsConfig.ts
│ │ │ ├── extensions/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── extensionService.ts
│ │ │ │ │ ├── extensionUrlHandler.ts
│ │ │ │ │ ├── extensionsScannerService.ts
│ │ │ │ │ ├── webWorkerExtensionHost.ts
│ │ │ │ │ └── webWorkerFileSystemProvider.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractExtensionService.ts
│ │ │ │ │ ├── extHostCustomers.ts
│ │ │ │ │ ├── extensionDescriptionRegistry.ts
│ │ │ │ │ ├── extensionDevOptions.ts
│ │ │ │ │ ├── extensionHostEnv.ts
│ │ │ │ │ ├── extensionHostKind.ts
│ │ │ │ │ ├── extensionHostManager.ts
│ │ │ │ │ ├── extensionHostManagers.ts
│ │ │ │ │ ├── extensionHostProtocol.ts
│ │ │ │ │ ├── extensionHostProxy.ts
│ │ │ │ │ ├── extensionManifestPropertiesService.ts
│ │ │ │ │ ├── extensionRunningLocation.ts
│ │ │ │ │ ├── extensionRunningLocationTracker.ts
│ │ │ │ │ ├── extensionStorageMigration.ts
│ │ │ │ │ ├── extensions.ts
│ │ │ │ │ ├── extensionsProposedApi.ts
│ │ │ │ │ ├── extensionsRegistry.ts
│ │ │ │ │ ├── extensionsUtil.ts
│ │ │ │ │ ├── lazyCreateExtensionHostManager.ts
│ │ │ │ │ ├── lazyPromise.ts
│ │ │ │ │ ├── polyfillNestedWorker.protocol.ts
│ │ │ │ │ ├── proxyIdentifier.ts
│ │ │ │ │ ├── remoteConsoleUtil.ts
│ │ │ │ │ ├── remoteExtensionHost.ts
│ │ │ │ │ ├── rpcProtocol.ts
│ │ │ │ │ └── workspaceContains.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── cachedExtensionScanner.ts
│ │ │ │ │ ├── extensionHostProfiler.ts
│ │ │ │ │ ├── extensionHostStarter.ts
│ │ │ │ │ ├── extensionsScannerService.ts
│ │ │ │ │ ├── localProcessExtensionHost.ts
│ │ │ │ │ └── nativeExtensionService.ts
│ │ │ │ ├── test/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ ├── extensionService.test.ts
│ │ │ │ │ │ └── extensionStorageMigration.test.ts
│ │ │ │ │ └── common/
│ │ │ │ │ ├── extensionDescriptionRegistry.test.ts
│ │ │ │ │ ├── extensionManifestPropertiesService.test.ts
│ │ │ │ │ └── rpcProtocol.test.ts
│ │ │ │ └── worker/
│ │ │ │ ├── polyfillNestedWorker.ts
│ │ │ │ └── webWorkerExtensionHostIframe.html
│ │ │ ├── files/
│ │ │ │ ├── browser/
│ │ │ │ │ └── elevatedFileService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── elevatedFileService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── diskFileSystemProvider.ts
│ │ │ │ ├── elevatedFileService.ts
│ │ │ │ └── watcherClient.ts
│ │ │ ├── filesConfiguration/
│ │ │ │ └── common/
│ │ │ │ └── filesConfigurationService.ts
│ │ │ ├── history/
│ │ │ │ ├── browser/
│ │ │ │ │ └── historyService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── history.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── historyService.test.ts
│ │ │ ├── host/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserHostService.ts
│ │ │ │ │ └── host.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── nativeHostService.ts
│ │ │ ├── integrity/
│ │ │ │ ├── browser/
│ │ │ │ │ └── integrityService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── integrity.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── integrityService.ts
│ │ │ ├── keybinding/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── keybindingService.ts
│ │ │ │ │ ├── keyboardLayoutService.ts
│ │ │ │ │ ├── keyboardLayouts/
│ │ │ │ │ │ ├── _.contribution.ts
│ │ │ │ │ │ ├── cz.win.ts
│ │ │ │ │ │ ├── de-swiss.win.ts
│ │ │ │ │ │ ├── de.darwin.ts
│ │ │ │ │ │ ├── de.linux.ts
│ │ │ │ │ │ ├── de.win.ts
│ │ │ │ │ │ ├── dk.win.ts
│ │ │ │ │ │ ├── dvorak.darwin.ts
│ │ │ │ │ │ ├── en-belgian.win.ts
│ │ │ │ │ │ ├── en-ext.darwin.ts
│ │ │ │ │ │ ├── en-in.win.ts
│ │ │ │ │ │ ├── en-intl.darwin.ts
│ │ │ │ │ │ ├── en-intl.win.ts
│ │ │ │ │ │ ├── en-uk.darwin.ts
│ │ │ │ │ │ ├── en-uk.win.ts
│ │ │ │ │ │ ├── en.darwin.ts
│ │ │ │ │ │ ├── en.linux.ts
│ │ │ │ │ │ ├── en.win.ts
│ │ │ │ │ │ ├── es-latin.win.ts
│ │ │ │ │ │ ├── es.darwin.ts
│ │ │ │ │ │ ├── es.linux.ts
│ │ │ │ │ │ ├── es.win.ts
│ │ │ │ │ │ ├── fr.darwin.ts
│ │ │ │ │ │ ├── fr.linux.ts
│ │ │ │ │ │ ├── fr.win.ts
│ │ │ │ │ │ ├── hu.win.ts
│ │ │ │ │ │ ├── it.darwin.ts
│ │ │ │ │ │ ├── it.win.ts
│ │ │ │ │ │ ├── jp-roman.darwin.ts
│ │ │ │ │ │ ├── jp.darwin.ts
│ │ │ │ │ │ ├── ko.darwin.ts
│ │ │ │ │ │ ├── layout.contribution.darwin.ts
│ │ │ │ │ │ ├── layout.contribution.linux.ts
│ │ │ │ │ │ ├── layout.contribution.win.ts
│ │ │ │ │ │ ├── no.win.ts
│ │ │ │ │ │ ├── pl.darwin.ts
│ │ │ │ │ │ ├── pl.win.ts
│ │ │ │ │ │ ├── pt-br.win.ts
│ │ │ │ │ │ ├── pt.darwin.ts
│ │ │ │ │ │ ├── pt.win.ts
│ │ │ │ │ │ ├── ru.darwin.ts
│ │ │ │ │ │ ├── ru.linux.ts
│ │ │ │ │ │ ├── ru.win.ts
│ │ │ │ │ │ ├── sv.darwin.ts
│ │ │ │ │ │ ├── sv.win.ts
│ │ │ │ │ │ ├── thai.win.ts
│ │ │ │ │ │ ├── tr.win.ts
│ │ │ │ │ │ └── zh-hans.darwin.ts
│ │ │ │ │ ├── navigatorKeyboard.ts
│ │ │ │ │ └── unboundCommands.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── fallbackKeyboardMapper.ts
│ │ │ │ │ ├── keybindingEditing.ts
│ │ │ │ │ ├── keybindingIO.ts
│ │ │ │ │ ├── keymapInfo.ts
│ │ │ │ │ ├── macLinuxKeyboardMapper.ts
│ │ │ │ │ └── windowsKeyboardMapper.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── nativeKeyboardLayout.ts
│ │ │ │ │ └── nativeKeyboardLayoutService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserKeyboardMapper.test.ts
│ │ │ │ │ ├── keybindingEditing.test.ts
│ │ │ │ │ └── keybindingIO.test.ts
│ │ │ │ └── node/
│ │ │ │ ├── fallbackKeyboardMapper.test.ts
│ │ │ │ ├── keyboardMapperTestUtils.ts
│ │ │ │ ├── linux_de_ch.js
│ │ │ │ ├── linux_de_ch.txt
│ │ │ │ ├── linux_en_uk.js
│ │ │ │ ├── linux_en_uk.txt
│ │ │ │ ├── linux_en_us.js
│ │ │ │ ├── linux_en_us.txt
│ │ │ │ ├── linux_ru.js
│ │ │ │ ├── linux_ru.txt
│ │ │ │ ├── macLinuxKeyboardMapper.test.ts
│ │ │ │ ├── mac_de_ch.js
│ │ │ │ ├── mac_de_ch.txt
│ │ │ │ ├── mac_en_us.js
│ │ │ │ ├── mac_en_us.txt
│ │ │ │ ├── mac_zh_hant.js
│ │ │ │ ├── mac_zh_hant.txt
│ │ │ │ ├── mac_zh_hant2.js
│ │ │ │ ├── mac_zh_hant2.txt
│ │ │ │ ├── win_de_ch.js
│ │ │ │ ├── win_de_ch.txt
│ │ │ │ ├── win_en_us.js
│ │ │ │ ├── win_en_us.txt
│ │ │ │ ├── win_por_ptb.js
│ │ │ │ ├── win_por_ptb.txt
│ │ │ │ ├── win_ru.js
│ │ │ │ ├── win_ru.txt
│ │ │ │ └── windowsKeyboardMapper.test.ts
│ │ │ ├── label/
│ │ │ │ ├── common/
│ │ │ │ │ └── labelService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ └── label.test.ts
│ │ │ │ └── common/
│ │ │ │ └── mockLabelService.ts
│ │ │ ├── language/
│ │ │ │ └── common/
│ │ │ │ └── languageService.ts
│ │ │ ├── languageDetection/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── languageDetectionWebWorker.ts
│ │ │ │ │ ├── languageDetectionWebWorkerMain.ts
│ │ │ │ │ ├── languageDetectionWorker.protocol.ts
│ │ │ │ │ └── languageDetectionWorkerServiceImpl.ts
│ │ │ │ └── common/
│ │ │ │ └── languageDetectionWorkerService.ts
│ │ │ ├── languageStatus/
│ │ │ │ └── common/
│ │ │ │ └── languageStatusService.ts
│ │ │ ├── layout/
│ │ │ │ └── browser/
│ │ │ │ └── layoutService.ts
│ │ │ ├── lifecycle/
│ │ │ │ ├── browser/
│ │ │ │ │ └── lifecycleService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── lifecycle.ts
│ │ │ │ │ └── lifecycleService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── lifecycleService.ts
│ │ │ │ └── test/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── lifecycleService.test.ts
│ │ │ ├── localization/
│ │ │ │ ├── browser/
│ │ │ │ │ └── localeService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── locale.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── languagePackService.ts
│ │ │ │ └── localeService.ts
│ │ │ ├── log/
│ │ │ │ ├── common/
│ │ │ │ │ └── logConstants.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── logService.ts
│ │ │ ├── menubar/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── menubarService.ts
│ │ │ ├── model/
│ │ │ │ └── common/
│ │ │ │ └── modelService.ts
│ │ │ ├── notebook/
│ │ │ │ └── common/
│ │ │ │ └── notebookDocumentService.ts
│ │ │ ├── notification/
│ │ │ │ └── common/
│ │ │ │ └── notificationService.ts
│ │ │ ├── outline/
│ │ │ │ └── browser/
│ │ │ │ ├── outline.ts
│ │ │ │ └── outlineService.ts
│ │ │ ├── output/
│ │ │ │ └── common/
│ │ │ │ ├── delayedLogChannel.ts
│ │ │ │ └── output.ts
│ │ │ ├── panecomposite/
│ │ │ │ └── browser/
│ │ │ │ └── panecomposite.ts
│ │ │ ├── path/
│ │ │ │ ├── browser/
│ │ │ │ │ └── pathService.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── pathService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── pathService.ts
│ │ │ ├── policies/
│ │ │ │ └── common/
│ │ │ │ ├── accountPolicyService.ts
│ │ │ │ └── multiplexPolicyService.ts
│ │ │ ├── preferences/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── keybindingsEditorInput.ts
│ │ │ │ │ ├── keybindingsEditorModel.ts
│ │ │ │ │ └── preferencesService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── preferences.ts
│ │ │ │ │ ├── preferencesEditorInput.ts
│ │ │ │ │ ├── preferencesModels.ts
│ │ │ │ │ └── preferencesValidation.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── keybindingsEditorModel.test.ts
│ │ │ │ │ └── preferencesService.test.ts
│ │ │ │ └── common/
│ │ │ │ └── preferencesValidation.test.ts
│ │ │ ├── progress/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── progressService.css
│ │ │ │ │ ├── progressIndicator.ts
│ │ │ │ │ └── progressService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── progressIndicator.test.ts
│ │ │ ├── quickinput/
│ │ │ │ └── browser/
│ │ │ │ └── quickInputService.ts
│ │ │ ├── remote/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserRemoteResourceHandler.ts
│ │ │ │ │ └── remoteAgentService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractRemoteAgentService.ts
│ │ │ │ │ ├── remoteAgentEnvironmentChannel.ts
│ │ │ │ │ ├── remoteAgentService.ts
│ │ │ │ │ ├── remoteExplorerService.ts
│ │ │ │ │ ├── remoteExtensionsScanner.ts
│ │ │ │ │ ├── remoteFileSystemProviderClient.ts
│ │ │ │ │ └── tunnelModel.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── remoteAgentService.ts
│ │ │ ├── request/
│ │ │ │ ├── browser/
│ │ │ │ │ └── requestService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── requestService.ts
│ │ │ ├── search/
│ │ │ │ ├── browser/
│ │ │ │ │ └── searchService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── fileSearchManager.ts
│ │ │ │ │ ├── folderQuerySearchTree.ts
│ │ │ │ │ ├── getFileResults.ts
│ │ │ │ │ ├── ignoreFile.ts
│ │ │ │ │ ├── localFileSearchWorkerTypes.ts
│ │ │ │ │ ├── queryBuilder.ts
│ │ │ │ │ ├── replace.ts
│ │ │ │ │ ├── search.ts
│ │ │ │ │ ├── searchExtConversionTypes.ts
│ │ │ │ │ ├── searchExtTypes.ts
│ │ │ │ │ ├── searchExtTypesInternal.ts
│ │ │ │ │ ├── searchHelpers.ts
│ │ │ │ │ ├── searchService.ts
│ │ │ │ │ └── textSearchManager.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── searchService.ts
│ │ │ │ ├── node/
│ │ │ │ │ ├── fileSearch.ts
│ │ │ │ │ ├── rawSearchService.ts
│ │ │ │ │ ├── ripgrepFileSearch.ts
│ │ │ │ │ ├── ripgrepSearchProvider.ts
│ │ │ │ │ ├── ripgrepSearchUtils.ts
│ │ │ │ │ ├── ripgrepTextSearchEngine.ts
│ │ │ │ │ ├── textSearchAdapter.ts
│ │ │ │ │ └── textSearchManager.ts
│ │ │ │ ├── test/
│ │ │ │ │ ├── browser/
│ │ │ │ │ │ └── queryBuilder.test.ts
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── folderQuerySearchTree.test.ts
│ │ │ │ │ │ ├── ignoreFile.test.ts
│ │ │ │ │ │ ├── queryBuilder.test.ts
│ │ │ │ │ │ ├── replace.test.ts
│ │ │ │ │ │ ├── search.test.ts
│ │ │ │ │ │ └── searchHelpers.test.ts
│ │ │ │ │ └── node/
│ │ │ │ │ ├── fileSearch.integrationTest.ts
│ │ │ │ │ ├── fixtures/
│ │ │ │ │ │ ├── binary.wuff
│ │ │ │ │ │ ├── examples/
│ │ │ │ │ │ │ ├── NullPoinderException.js
│ │ │ │ │ │ │ ├── company.js
│ │ │ │ │ │ │ ├── employee.js
│ │ │ │ │ │ │ ├── small.js
│ │ │ │ │ │ │ └── subfolder/
│ │ │ │ │ │ │ ├── anotherfolder/
│ │ │ │ │ │ │ │ └── anotherfile.txt
│ │ │ │ │ │ │ └── subfile.txt
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── more/
│ │ │ │ │ │ │ └── file.txt
│ │ │ │ │ │ ├── site.css
│ │ │ │ │ │ ├── site.less
│ │ │ │ │ │ ├── some_utf16be.css
│ │ │ │ │ │ ├── some_utf16le.css
│ │ │ │ │ │ └── üm laut汉语/
│ │ │ │ │ │ └── 汉语.txt
│ │ │ │ │ ├── fixtures2/
│ │ │ │ │ │ └── 36438/
│ │ │ │ │ │ ├── modules/
│ │ │ │ │ │ │ └── do-not-find.txt
│ │ │ │ │ │ └── more/
│ │ │ │ │ │ └── modules/
│ │ │ │ │ │ └── find.txt
│ │ │ │ │ ├── rawSearchService.integrationTest.ts
│ │ │ │ │ ├── ripgrepFileSearch.test.ts
│ │ │ │ │ ├── ripgrepTextSearchEngineUtils.test.ts
│ │ │ │ │ ├── search.integrationTest.ts
│ │ │ │ │ ├── textSearch.integrationTest.ts
│ │ │ │ │ └── textSearchManager.test.ts
│ │ │ │ └── worker/
│ │ │ │ ├── localFileSearch.ts
│ │ │ │ └── localFileSearchMain.ts
│ │ │ ├── secrets/
│ │ │ │ ├── browser/
│ │ │ │ │ └── secretStorageService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── secretStorageService.ts
│ │ │ ├── sharedProcess/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── sharedProcessService.ts
│ │ │ ├── statusbar/
│ │ │ │ └── browser/
│ │ │ │ └── statusbar.ts
│ │ │ ├── storage/
│ │ │ │ ├── browser/
│ │ │ │ │ └── storageService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── storageService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── storageService.test.ts
│ │ │ ├── suggest/
│ │ │ │ └── browser/
│ │ │ │ ├── media/
│ │ │ │ │ └── suggest.css
│ │ │ │ ├── simpleCompletionItem.ts
│ │ │ │ ├── simpleCompletionModel.ts
│ │ │ │ ├── simpleSuggestWidget.ts
│ │ │ │ ├── simpleSuggestWidgetDetails.ts
│ │ │ │ └── simpleSuggestWidgetRenderer.ts
│ │ │ ├── telemetry/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── telemetryService.ts
│ │ │ │ │ └── workbenchCommonProperties.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── workbenchCommonProperties.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── telemetryService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ └── commonProperties.test.ts
│ │ │ │ └── node/
│ │ │ │ └── commonProperties.test.ts
│ │ │ ├── terminal/
│ │ │ │ └── common/
│ │ │ │ └── embedderTerminalService.ts
│ │ │ ├── textMate/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── arrayOperation.ts
│ │ │ │ │ ├── backgroundTokenization/
│ │ │ │ │ │ ├── textMateWorkerTokenizerController.ts
│ │ │ │ │ │ ├── threadedBackgroundTokenizerFactory.ts
│ │ │ │ │ │ └── worker/
│ │ │ │ │ │ ├── textMateTokenizationWorker.worker.ts
│ │ │ │ │ │ ├── textMateTokenizationWorker.workerMain.ts
│ │ │ │ │ │ ├── textMateWorkerHost.ts
│ │ │ │ │ │ └── textMateWorkerTokenizer.ts
│ │ │ │ │ ├── textMateTokenizationFeature.contribution.ts
│ │ │ │ │ ├── textMateTokenizationFeature.ts
│ │ │ │ │ ├── textMateTokenizationFeatureImpl.ts
│ │ │ │ │ └── tokenizationSupport/
│ │ │ │ │ ├── textMateTokenizationSupport.ts
│ │ │ │ │ └── tokenizationSupportWithLineLimit.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── TMGrammarFactory.ts
│ │ │ │ │ ├── TMGrammars.ts
│ │ │ │ │ ├── TMHelper.ts
│ │ │ │ │ ├── TMScopeRegistry.ts
│ │ │ │ │ └── cgmanifest.json
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── arrayOperation.test.ts
│ │ │ ├── textfile/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserTextFileService.ts
│ │ │ │ │ └── textFileService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── encoding.ts
│ │ │ │ │ ├── textEditorService.ts
│ │ │ │ │ ├── textFileEditorModel.ts
│ │ │ │ │ ├── textFileEditorModelManager.ts
│ │ │ │ │ ├── textFileSaveParticipant.ts
│ │ │ │ │ └── textfiles.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ └── nativeTextFileService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserTextFileService.io.test.ts
│ │ │ │ │ ├── textEditorService.test.ts
│ │ │ │ │ ├── textFileEditorModel.integrationTest.ts
│ │ │ │ │ ├── textFileEditorModel.test.ts
│ │ │ │ │ ├── textFileEditorModelManager.test.ts
│ │ │ │ │ └── textFileService.test.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── fixtures/
│ │ │ │ │ │ └── files.ts
│ │ │ │ │ └── textFileService.io.test.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── nativeTextFileService.io.test.ts
│ │ │ │ │ └── nativeTextFileService.test.ts
│ │ │ │ └── node/
│ │ │ │ └── encoding/
│ │ │ │ ├── encoding.integrationTest.ts
│ │ │ │ ├── encoding.test.ts
│ │ │ │ └── fixtures/
│ │ │ │ ├── empty.txt
│ │ │ │ ├── issue_102202.txt
│ │ │ │ ├── some.cp1252.txt
│ │ │ │ ├── some.css.qwoff
│ │ │ │ ├── some.png.txt
│ │ │ │ ├── some.qwoff.txt
│ │ │ │ ├── some.shiftjis.1.txt
│ │ │ │ ├── some.shiftjis.txt
│ │ │ │ ├── some_ansi.css
│ │ │ │ ├── some_file.css
│ │ │ │ ├── some_gbk.txt
│ │ │ │ ├── some_utf16be.css
│ │ │ │ ├── some_utf16le.css
│ │ │ │ ├── some_utf8.css
│ │ │ │ ├── utf16_be_nobom.txt
│ │ │ │ └── utf16_le_nobom.txt
│ │ │ ├── textmodelResolver/
│ │ │ │ ├── common/
│ │ │ │ │ └── textModelResolverService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ └── textModelResolverService.test.ts
│ │ │ ├── textresourceProperties/
│ │ │ │ └── common/
│ │ │ │ └── textResourcePropertiesService.ts
│ │ │ ├── themes/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── browserHostColorSchemeService.ts
│ │ │ │ │ ├── fileIconThemeData.ts
│ │ │ │ │ ├── productIconThemeData.ts
│ │ │ │ │ └── workbenchThemeService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── colorExtensionPoint.ts
│ │ │ │ │ ├── colorThemeData.ts
│ │ │ │ │ ├── colorThemeSchema.ts
│ │ │ │ │ ├── fileIconThemeSchema.ts
│ │ │ │ │ ├── hostColorSchemeService.ts
│ │ │ │ │ ├── iconExtensionPoint.ts
│ │ │ │ │ ├── plistParser.ts
│ │ │ │ │ ├── productIconThemeSchema.ts
│ │ │ │ │ ├── textMateScopeMatcher.ts
│ │ │ │ │ ├── themeCompatibility.ts
│ │ │ │ │ ├── themeConfiguration.ts
│ │ │ │ │ ├── themeExtensionPoints.ts
│ │ │ │ │ ├── tokenClassificationExtensionPoint.ts
│ │ │ │ │ └── workbenchThemeService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── nativeHostColorSchemeService.ts
│ │ │ │ │ └── themes.contribution.ts
│ │ │ │ └── test/
│ │ │ │ └── node/
│ │ │ │ ├── color-theme.json
│ │ │ │ └── tokenStyleResolving.test.ts
│ │ │ ├── timer/
│ │ │ │ ├── browser/
│ │ │ │ │ └── timerService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── timerService.ts
│ │ │ ├── title/
│ │ │ │ ├── browser/
│ │ │ │ │ └── titleService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── titleService.ts
│ │ │ ├── treeSitter/
│ │ │ │ └── browser/
│ │ │ │ ├── treeSitterCodeEditors.ts
│ │ │ │ ├── treeSitterTokenizationFeature.contribution.ts
│ │ │ │ └── treeSitterTokenizationFeature.ts
│ │ │ ├── tunnel/
│ │ │ │ ├── browser/
│ │ │ │ │ └── tunnelService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── tunnelService.ts
│ │ │ ├── untitled/
│ │ │ │ ├── common/
│ │ │ │ │ ├── untitledTextEditorHandler.ts
│ │ │ │ │ ├── untitledTextEditorInput.ts
│ │ │ │ │ ├── untitledTextEditorModel.ts
│ │ │ │ │ └── untitledTextEditorService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── untitledTextEditor.integrationTest.ts
│ │ │ │ └── untitledTextEditor.test.ts
│ │ │ ├── update/
│ │ │ │ ├── browser/
│ │ │ │ │ └── updateService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── updateService.ts
│ │ │ ├── url/
│ │ │ │ ├── browser/
│ │ │ │ │ └── urlService.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── urlService.ts
│ │ │ ├── userActivity/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── domActivityTracker.ts
│ │ │ │ │ └── userActivityBrowser.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── userActivityRegistry.ts
│ │ │ │ │ └── userActivityService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ └── domActivityTracker.test.ts
│ │ │ │ └── common/
│ │ │ │ └── userActivityService.test.ts
│ │ │ ├── userData/
│ │ │ │ └── browser/
│ │ │ │ └── userDataInit.ts
│ │ │ ├── userDataProfile/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── extensionsResource.ts
│ │ │ │ │ ├── globalStateResource.ts
│ │ │ │ │ ├── iconSelectBox.ts
│ │ │ │ │ ├── keybindingsResource.ts
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── userDataProfileView.css
│ │ │ │ │ ├── settingsResource.ts
│ │ │ │ │ ├── snippetsResource.ts
│ │ │ │ │ ├── tasksResource.ts
│ │ │ │ │ ├── userDataProfileImportExportService.ts
│ │ │ │ │ ├── userDataProfileInit.ts
│ │ │ │ │ ├── userDataProfileManagement.ts
│ │ │ │ │ └── userDataProfileStorageService.ts
│ │ │ │ └── common/
│ │ │ │ ├── remoteUserDataProfiles.ts
│ │ │ │ ├── userDataProfile.ts
│ │ │ │ ├── userDataProfileIcons.ts
│ │ │ │ └── userDataProfileService.ts
│ │ │ ├── userDataSync/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── userDataSyncEnablementService.ts
│ │ │ │ │ ├── userDataSyncInit.ts
│ │ │ │ │ ├── userDataSyncWorkbenchService.ts
│ │ │ │ │ └── webUserDataSyncEnablementService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── userDataSync.ts
│ │ │ │ │ └── userDataSyncUtil.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── userDataAutoSyncService.ts
│ │ │ │ └── userDataSyncService.ts
│ │ │ ├── utilityProcess/
│ │ │ │ └── electron-sandbox/
│ │ │ │ └── utilityProcessWorkerWorkbenchService.ts
│ │ │ ├── views/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── viewDescriptorService.ts
│ │ │ │ │ └── viewsService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── viewContainerModel.ts
│ │ │ │ │ └── viewsService.ts
│ │ │ │ └── test/
│ │ │ │ └── browser/
│ │ │ │ ├── viewContainerModel.test.ts
│ │ │ │ └── viewDescriptorService.test.ts
│ │ │ ├── workingCopy/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── workingCopyBackupService.ts
│ │ │ │ │ ├── workingCopyBackupTracker.ts
│ │ │ │ │ └── workingCopyHistoryService.ts
│ │ │ │ ├── common/
│ │ │ │ │ ├── abstractFileWorkingCopyManager.ts
│ │ │ │ │ ├── fileWorkingCopy.ts
│ │ │ │ │ ├── fileWorkingCopyManager.ts
│ │ │ │ │ ├── resourceWorkingCopy.ts
│ │ │ │ │ ├── storedFileWorkingCopy.ts
│ │ │ │ │ ├── storedFileWorkingCopyManager.ts
│ │ │ │ │ ├── storedFileWorkingCopySaveParticipant.ts
│ │ │ │ │ ├── untitledFileWorkingCopy.ts
│ │ │ │ │ ├── untitledFileWorkingCopyManager.ts
│ │ │ │ │ ├── workingCopy.ts
│ │ │ │ │ ├── workingCopyBackup.ts
│ │ │ │ │ ├── workingCopyBackupService.ts
│ │ │ │ │ ├── workingCopyBackupTracker.ts
│ │ │ │ │ ├── workingCopyEditorService.ts
│ │ │ │ │ ├── workingCopyFileOperationParticipant.ts
│ │ │ │ │ ├── workingCopyFileService.ts
│ │ │ │ │ ├── workingCopyHistory.ts
│ │ │ │ │ ├── workingCopyHistoryService.ts
│ │ │ │ │ ├── workingCopyHistoryTracker.ts
│ │ │ │ │ └── workingCopyService.ts
│ │ │ │ ├── electron-sandbox/
│ │ │ │ │ ├── workingCopyBackupService.ts
│ │ │ │ │ ├── workingCopyBackupTracker.ts
│ │ │ │ │ └── workingCopyHistoryService.ts
│ │ │ │ └── test/
│ │ │ │ ├── browser/
│ │ │ │ │ ├── fileWorkingCopyManager.test.ts
│ │ │ │ │ ├── resourceWorkingCopy.test.ts
│ │ │ │ │ ├── storedFileWorkingCopy.test.ts
│ │ │ │ │ ├── storedFileWorkingCopyManager.test.ts
│ │ │ │ │ ├── untitledFileWorkingCopy.test.ts
│ │ │ │ │ ├── untitledFileWorkingCopyManager.test.ts
│ │ │ │ │ ├── untitledScratchpadWorkingCopy.test.ts
│ │ │ │ │ ├── workingCopyBackupTracker.test.ts
│ │ │ │ │ ├── workingCopyEditorService.test.ts
│ │ │ │ │ └── workingCopyFileService.test.ts
│ │ │ │ ├── common/
│ │ │ │ │ └── workingCopyService.test.ts
│ │ │ │ └── electron-sandbox/
│ │ │ │ ├── workingCopyBackupService.test.ts
│ │ │ │ ├── workingCopyBackupTracker.test.ts
│ │ │ │ ├── workingCopyHistoryService.test.ts
│ │ │ │ └── workingCopyHistoryTracker.test.ts
│ │ │ └── workspaces/
│ │ │ ├── browser/
│ │ │ │ ├── abstractWorkspaceEditingService.ts
│ │ │ │ ├── workspaceEditingService.ts
│ │ │ │ ├── workspaceTrustEditorInput.ts
│ │ │ │ ├── workspaces.ts
│ │ │ │ └── workspacesService.ts
│ │ │ ├── common/
│ │ │ │ ├── canonicalUriService.ts
│ │ │ │ ├── editSessionIdentityService.ts
│ │ │ │ ├── workspaceEditing.ts
│ │ │ │ ├── workspaceIdentityService.ts
│ │ │ │ ├── workspaceTrust.ts
│ │ │ │ └── workspaceUtils.ts
│ │ │ ├── electron-sandbox/
│ │ │ │ ├── workspaceEditingService.ts
│ │ │ │ └── workspacesService.ts
│ │ │ └── test/
│ │ │ ├── browser/
│ │ │ │ └── workspaces.test.ts
│ │ │ └── common/
│ │ │ └── workspaceTrust.test.ts
│ │ ├── test/
│ │ │ ├── browser/
│ │ │ │ ├── codeeditor.test.ts
│ │ │ │ ├── contributions.test.ts
│ │ │ │ ├── part.test.ts
│ │ │ │ ├── parts/
│ │ │ │ │ ├── editor/
│ │ │ │ │ │ ├── breadcrumbModel.test.ts
│ │ │ │ │ │ ├── diffEditorInput.test.ts
│ │ │ │ │ │ ├── editor.test.ts
│ │ │ │ │ │ ├── editorCommandsContext.test.ts
│ │ │ │ │ │ ├── editorDiffModel.test.ts
│ │ │ │ │ │ ├── editorGroupModel.test.ts
│ │ │ │ │ │ ├── editorInput.test.ts
│ │ │ │ │ │ ├── editorModel.test.ts
│ │ │ │ │ │ ├── editorPane.test.ts
│ │ │ │ │ │ ├── filteredEditorGroupModel.test.ts
│ │ │ │ │ │ ├── resourceEditorInput.test.ts
│ │ │ │ │ │ ├── sideBySideEditorInput.test.ts
│ │ │ │ │ │ ├── textEditorPane.test.ts
│ │ │ │ │ │ └── textResourceEditorInput.test.ts
│ │ │ │ │ └── statusbar/
│ │ │ │ │ └── statusbarModel.test.ts
│ │ │ │ ├── quickAccess.test.ts
│ │ │ │ ├── treeview.test.ts
│ │ │ │ ├── viewlet.test.ts
│ │ │ │ ├── webview.test.ts
│ │ │ │ ├── window.test.ts
│ │ │ │ └── workbenchTestServices.ts
│ │ │ ├── common/
│ │ │ │ ├── memento.test.ts
│ │ │ │ ├── notifications.test.ts
│ │ │ │ ├── resources.test.ts
│ │ │ │ ├── utils.ts
│ │ │ │ └── workbenchTestServices.ts
│ │ │ ├── electron-main/
│ │ │ │ └── treeSitterTokenizationFeature.test.ts
│ │ │ └── electron-sandbox/
│ │ │ ├── resolveExternal.test.ts
│ │ │ └── workbenchTestServices.ts
│ │ ├── workbench.common.main.ts
│ │ ├── workbench.desktop.main.ts
│ │ ├── workbench.web.main.internal.ts
│ │ └── workbench.web.main.ts
│ └── vscode-dts/
│ ├── README.md
│ ├── vscode.d.ts
│ ├── vscode.proposed.activeComment.d.ts
│ ├── vscode.proposed.aiRelatedInformation.d.ts
│ ├── vscode.proposed.aiTextSearchProvider.d.ts
│ ├── vscode.proposed.authLearnMore.d.ts
│ ├── vscode.proposed.authSession.d.ts
│ ├── vscode.proposed.canonicalUriProvider.d.ts
│ ├── vscode.proposed.chatEditing.d.ts
│ ├── vscode.proposed.chatParticipantAdditions.d.ts
│ ├── vscode.proposed.chatParticipantPrivate.d.ts
│ ├── vscode.proposed.chatProvider.d.ts
│ ├── vscode.proposed.chatReferenceBinaryData.d.ts
│ ├── vscode.proposed.chatReferenceDiagnostic.d.ts
│ ├── vscode.proposed.chatStatusItem.d.ts
│ ├── vscode.proposed.chatTab.d.ts
│ ├── vscode.proposed.codeActionAI.d.ts
│ ├── vscode.proposed.codeActionRanges.d.ts
│ ├── vscode.proposed.codiconDecoration.d.ts
│ ├── vscode.proposed.commentReactor.d.ts
│ ├── vscode.proposed.commentReveal.d.ts
│ ├── vscode.proposed.commentThreadApplicability.d.ts
│ ├── vscode.proposed.commentingRangeHint.d.ts
│ ├── vscode.proposed.commentsDraftState.d.ts
│ ├── vscode.proposed.contribAccessibilityHelpContent.d.ts
│ ├── vscode.proposed.contribCommentEditorActionsMenu.d.ts
│ ├── vscode.proposed.contribCommentPeekContext.d.ts
│ ├── vscode.proposed.contribCommentThreadAdditionalMenu.d.ts
│ ├── vscode.proposed.contribCommentsViewThreadMenus.d.ts
│ ├── vscode.proposed.contribDebugCreateConfiguration.d.ts
│ ├── vscode.proposed.contribDiffEditorGutterToolBarMenus.d.ts
│ ├── vscode.proposed.contribEditSessions.d.ts
│ ├── vscode.proposed.contribEditorContentMenu.d.ts
│ ├── vscode.proposed.contribLabelFormatterWorkspaceTooltip.d.ts
│ ├── vscode.proposed.contribMenuBarHome.d.ts
│ ├── vscode.proposed.contribMergeEditorMenus.d.ts
│ ├── vscode.proposed.contribMultiDiffEditorMenus.d.ts
│ ├── vscode.proposed.contribNotebookStaticPreloads.d.ts
│ ├── vscode.proposed.contribRemoteHelp.d.ts
│ ├── vscode.proposed.contribShareMenu.d.ts
│ ├── vscode.proposed.contribSourceControlHistoryItemMenu.d.ts
│ ├── vscode.proposed.contribSourceControlHistoryTitleMenu.d.ts
│ ├── vscode.proposed.contribSourceControlInputBoxMenu.d.ts
│ ├── vscode.proposed.contribSourceControlTitleMenu.d.ts
│ ├── vscode.proposed.contribStatusBarItems.d.ts
│ ├── vscode.proposed.contribViewContainerTitle.d.ts
│ ├── vscode.proposed.contribViewsRemote.d.ts
│ ├── vscode.proposed.contribViewsWelcome.d.ts
│ ├── vscode.proposed.customEditorMove.d.ts
│ ├── vscode.proposed.debugVisualization.d.ts
│ ├── vscode.proposed.defaultChatParticipant.d.ts
│ ├── vscode.proposed.diffCommand.d.ts
│ ├── vscode.proposed.diffContentOptions.d.ts
│ ├── vscode.proposed.documentFiltersExclusive.d.ts
│ ├── vscode.proposed.editSessionIdentityProvider.d.ts
│ ├── vscode.proposed.editorHoverVerbosityLevel.d.ts
│ ├── vscode.proposed.editorInsets.d.ts
│ ├── vscode.proposed.embeddings.d.ts
│ ├── vscode.proposed.extensionRuntime.d.ts
│ ├── vscode.proposed.extensionsAny.d.ts
│ ├── vscode.proposed.externalUriOpener.d.ts
│ ├── vscode.proposed.fileSearchProvider.d.ts
│ ├── vscode.proposed.fileSearchProvider2.d.ts
│ ├── vscode.proposed.findFiles2.d.ts
│ ├── vscode.proposed.findTextInFiles.d.ts
│ ├── vscode.proposed.findTextInFiles2.d.ts
│ ├── vscode.proposed.fsChunks.d.ts
│ ├── vscode.proposed.idToken.d.ts
│ ├── vscode.proposed.inlineCompletionsAdditions.d.ts
│ ├── vscode.proposed.inlineEdit.d.ts
│ ├── vscode.proposed.interactive.d.ts
│ ├── vscode.proposed.interactiveWindow.d.ts
│ ├── vscode.proposed.ipc.d.ts
│ ├── vscode.proposed.languageModelCapabilities.d.ts
│ ├── vscode.proposed.languageModelDataPart.d.ts
│ ├── vscode.proposed.languageModelSystem.d.ts
│ ├── vscode.proposed.languageModelToolsForAgent.d.ts
│ ├── vscode.proposed.languageStatusText.d.ts
│ ├── vscode.proposed.mappedEditsProvider.d.ts
│ ├── vscode.proposed.mcpConfigurationProvider.d.ts
│ ├── vscode.proposed.multiDocumentHighlightProvider.d.ts
│ ├── vscode.proposed.nativeWindowHandle.d.ts
│ ├── vscode.proposed.newSymbolNamesProvider.d.ts
│ ├── vscode.proposed.notebookCellExecution.d.ts
│ ├── vscode.proposed.notebookCellExecutionState.d.ts
│ ├── vscode.proposed.notebookControllerAffinityHidden.d.ts
│ ├── vscode.proposed.notebookDeprecated.d.ts
│ ├── vscode.proposed.notebookExecution.d.ts
│ ├── vscode.proposed.notebookKernelSource.d.ts
│ ├── vscode.proposed.notebookLiveShare.d.ts
│ ├── vscode.proposed.notebookMessaging.d.ts
│ ├── vscode.proposed.notebookMime.d.ts
│ ├── vscode.proposed.notebookReplDocument.d.ts
│ ├── vscode.proposed.notebookVariableProvider.d.ts
│ ├── vscode.proposed.portsAttributes.d.ts
│ ├── vscode.proposed.profileContentHandlers.d.ts
│ ├── vscode.proposed.quickDiffProvider.d.ts
│ ├── vscode.proposed.quickInputButtonLocation.d.ts
│ ├── vscode.proposed.quickPickItemTooltip.d.ts
│ ├── vscode.proposed.quickPickSortByLabel.d.ts
│ ├── vscode.proposed.resolvers.d.ts
│ ├── vscode.proposed.scmActionButton.d.ts
│ ├── vscode.proposed.scmHistoryProvider.d.ts
│ ├── vscode.proposed.scmMultiDiffEditor.d.ts
│ ├── vscode.proposed.scmSelectedProvider.d.ts
│ ├── vscode.proposed.scmTextDocument.d.ts
│ ├── vscode.proposed.scmValidation.d.ts
│ ├── vscode.proposed.shareProvider.d.ts
│ ├── vscode.proposed.speech.d.ts
│ ├── vscode.proposed.statusBarItemTooltip.d.ts
│ ├── vscode.proposed.tabInputMultiDiff.d.ts
│ ├── vscode.proposed.tabInputTextMerge.d.ts
│ ├── vscode.proposed.taskPresentationGroup.d.ts
│ ├── vscode.proposed.taskProblemMatcherStatus.d.ts
│ ├── vscode.proposed.telemetry.d.ts
│ ├── vscode.proposed.terminalCompletionProvider.d.ts
│ ├── vscode.proposed.terminalDataWriteEvent.d.ts
│ ├── vscode.proposed.terminalDimensions.d.ts
│ ├── vscode.proposed.terminalExecuteCommandEvent.d.ts
│ ├── vscode.proposed.terminalQuickFixProvider.d.ts
│ ├── vscode.proposed.terminalSelection.d.ts
│ ├── vscode.proposed.terminalShellEnv.d.ts
│ ├── vscode.proposed.testObserver.d.ts
│ ├── vscode.proposed.testRelatedCode.d.ts
│ ├── vscode.proposed.textDocumentEncoding.d.ts
│ ├── vscode.proposed.textEditorDiffInformation.d.ts
│ ├── vscode.proposed.textSearchComplete2.d.ts
│ ├── vscode.proposed.textSearchProvider.d.ts
│ ├── vscode.proposed.textSearchProvider2.d.ts
│ ├── vscode.proposed.timeline.d.ts
│ ├── vscode.proposed.tokenInformation.d.ts
│ ├── vscode.proposed.treeViewActiveItem.d.ts
│ ├── vscode.proposed.treeViewMarkdownMessage.d.ts
│ ├── vscode.proposed.treeViewReveal.d.ts
│ ├── vscode.proposed.tunnelFactory.d.ts
│ ├── vscode.proposed.tunnels.d.ts
│ ├── vscode.proposed.valueSelectionInQuickPick.d.ts
│ └── vscode.proposed.workspaceTrust.d.ts
├── test/
│ ├── .mocharc.json
│ ├── README.md
│ ├── automation/
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── activityBar.ts
│ │ │ ├── application.ts
│ │ │ ├── code.ts
│ │ │ ├── debug.ts
│ │ │ ├── editor.ts
│ │ │ ├── editors.ts
│ │ │ ├── electron.ts
│ │ │ ├── explorer.ts
│ │ │ ├── extensions.ts
│ │ │ ├── index.ts
│ │ │ ├── keybindings.ts
│ │ │ ├── localization.ts
│ │ │ ├── logger.ts
│ │ │ ├── notebook.ts
│ │ │ ├── peek.ts
│ │ │ ├── playwrightBrowser.ts
│ │ │ ├── playwrightDriver.ts
│ │ │ ├── playwrightElectron.ts
│ │ │ ├── problems.ts
│ │ │ ├── processes.ts
│ │ │ ├── profiler.ts
│ │ │ ├── quickaccess.ts
│ │ │ ├── quickinput.ts
│ │ │ ├── scm.ts
│ │ │ ├── search.ts
│ │ │ ├── settings.ts
│ │ │ ├── statusbar.ts
│ │ │ ├── task.ts
│ │ │ ├── terminal.ts
│ │ │ ├── viewlet.ts
│ │ │ └── workbench.ts
│ │ ├── tools/
│ │ │ ├── copy-driver-definition.js
│ │ │ └── copy-package-version.js
│ │ └── tsconfig.json
│ ├── cgmanifest.json
│ ├── integration/
│ │ ├── browser/
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ └── index.ts
│ │ │ └── tsconfig.json
│ │ └── electron/
│ │ ├── testrunner.d.ts
│ │ └── testrunner.js
│ ├── leaks/
│ │ ├── index.html
│ │ ├── package.json
│ │ └── server.js
│ ├── monaco/
│ │ ├── .gitignore
│ │ ├── .mocharc.json
│ │ ├── .npmrc
│ │ ├── README.md
│ │ ├── core.js
│ │ ├── dist/
│ │ │ └── core.html
│ │ ├── esm-check/
│ │ │ ├── esm-check.js
│ │ │ ├── index.html
│ │ │ └── index.js
│ │ ├── monaco.test.ts
│ │ ├── package.json
│ │ ├── runner.js
│ │ ├── tsconfig.json
│ │ └── webpack.config.js
│ ├── package.json
│ ├── smoke/
│ │ ├── .gitignore
│ │ ├── Audit.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── areas/
│ │ │ │ ├── extensions/
│ │ │ │ │ └── extensions.test.ts
│ │ │ │ ├── languages/
│ │ │ │ │ └── languages.test.ts
│ │ │ │ ├── multiroot/
│ │ │ │ │ └── multiroot.test.ts
│ │ │ │ ├── notebook/
│ │ │ │ │ └── notebook.test.ts
│ │ │ │ ├── preferences/
│ │ │ │ │ └── preferences.test.ts
│ │ │ │ ├── search/
│ │ │ │ │ └── search.test.ts
│ │ │ │ ├── statusbar/
│ │ │ │ │ └── statusbar.test.ts
│ │ │ │ ├── task/
│ │ │ │ │ ├── task-quick-pick.test.ts
│ │ │ │ │ └── task.test.ts
│ │ │ │ ├── terminal/
│ │ │ │ │ ├── terminal-editors.test.ts
│ │ │ │ │ ├── terminal-helpers.ts
│ │ │ │ │ ├── terminal-input.test.ts
│ │ │ │ │ ├── terminal-persistence.test.ts
│ │ │ │ │ ├── terminal-profiles.test.ts
│ │ │ │ │ ├── terminal-shellIntegration.test.ts
│ │ │ │ │ ├── terminal-splitCwd.test.ts
│ │ │ │ │ ├── terminal-stickyScroll.test.ts
│ │ │ │ │ ├── terminal-tabs.test.ts
│ │ │ │ │ └── terminal.test.ts
│ │ │ │ └── workbench/
│ │ │ │ ├── data-loss.test.ts
│ │ │ │ ├── launch.test.ts
│ │ │ │ └── localization.test.ts
│ │ │ ├── main.ts
│ │ │ └── utils.ts
│ │ ├── test/
│ │ │ └── index.js
│ │ └── tsconfig.json
│ └── unit/
│ ├── README.md
│ ├── analyzeSnapshot.js
│ ├── assert.js
│ ├── browser/
│ │ ├── index.js
│ │ └── renderer.html
│ ├── coverage.js
│ ├── electron/
│ │ ├── index.js
│ │ ├── preload.js
│ │ ├── renderer.html
│ │ └── renderer.js
│ ├── fullJsonStreamReporter.js
│ ├── node/
│ │ ├── index.js
│ │ └── package.json
│ └── reporter.js
└── tsfmt.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .config/1espt/PipelineAutobaseliningConfig.yml
================================================
## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details.
pipelines:
111:
retail:
source:
credscan:
lastModifiedDate: 2024-09-10
eslint:
lastModifiedDate: 2024-09-10
psscriptanalyzer:
lastModifiedDate: 2024-09-10
armory:
lastModifiedDate: 2024-09-10
binary:
credscan:
lastModifiedDate: 2025-02-04
binskim:
lastModifiedDate: 2025-02-04
spotbugs:
lastModifiedDate: 2025-02-04
================================================
FILE: .config/guardian/.gdnbaselines
================================================
{
"properties": {
"helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines"
},
"version": "1.0.0",
"baselines": {
"default": {
"name": "default",
"createdDate": "2025-01-28 06:29:05Z",
"lastUpdatedDate": "2025-01-28 06:29:05Z"
}
},
"results": {
"ea3b2bf4f5b3d0bd8a6ad35cc61e49f2a1596660fd66d17d740e4806e7ed7dcc": {
"signature": "ea3b2bf4f5b3d0bd8a6ad35cc61e49f2a1596660fd66d17d740e4806e7ed7dcc",
"alternativeSignatures": [
"ff528c0b5a010ae7b5e9178b004a8b816a429a28ba98ce8336466b490a09dcef"
],
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-01-30 19:19:49Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"12babbc85192ed1c8d927693da788537c1eef199bbecbe226f940a2d0e97637c": {
"signature": "12babbc85192ed1c8d927693da788537c1eef199bbecbe226f940a2d0e97637c",
"alternativeSignatures": [
"35b0519e201e56fb87fc6fb085e6fb1df5b89715142bb9086a5b2006e0fd4ced"
],
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-01-30 19:19:49Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"49163bd1dc9d965d3baced1694dc8c43305b8bf96e884f478d8e4bd124454ba0": {
"signature": "49163bd1dc9d965d3baced1694dc8c43305b8bf96e884f478d8e4bd124454ba0",
"alternativeSignatures": [
"aa80bcf44aa8ddd20fb9802e9032c1257048b973896a944ded70bb195f060b2a"
],
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-01-30 19:21:17Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"c405af02e021c3a473d4e45ec4daa658db1527ea7430c6be968d182e7b50fbd1": {
"signature": "c405af02e021c3a473d4e45ec4daa658db1527ea7430c6be968d182e7b50fbd1",
"alternativeSignatures": [
"619d2a1a77f55b4181493b8cfdf09be5261e539115752af2e4938f5ac04af132"
],
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-01-30 19:21:17Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"71b8515b2eb51cfd5eace11cedb15189d51ce9e479095a5938334416088cbc03": {
"signature": "71b8515b2eb51cfd5eace11cedb15189d51ce9e479095a5938334416088cbc03",
"alternativeSignatures": [
"b34279fc5fec828b8dcd9ca873804e85d7d9cd78554ec109d2dd493351a7a244"
],
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-01-30 19:51:51Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"9238de77a5320039def14694d1b6f501cc2288f13c9c688d2e0501fc5a56ee61": {
"signature": "9238de77a5320039def14694d1b6f501cc2288f13c9c688d2e0501fc5a56ee61",
"alternativeSignatures": [
"1d17616a549e9f36d814c4e802d651b1af453ce0a23d4478eef39be81adcc16b"
],
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-01-30 19:51:51Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"bad8b698b48c1da9ece953903581c66bf98bc829ae1a6adcd3b5c2056a6fcd01": {
"signature": "bad8b698b48c1da9ece953903581c66bf98bc829ae1a6adcd3b5c2056a6fcd01",
"alternativeSignatures": [
"057376d31b97e8ce3ecf6a180a553b932d7e5be6e2b07a08027d5dfabe35e82c"
],
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-01-30 19:53:13Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"cc7c248b0fd4c105e9a393ae232bf0d314ec50e65357a5e7e7d68f6f10c77077": {
"signature": "cc7c248b0fd4c105e9a393ae232bf0d314ec50e65357a5e7e7d68f6f10c77077",
"alternativeSignatures": [
"f3867098aff3368682df9926e85a35ec05cf905f27d0c157430021c3169f899d"
],
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.97.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-01-30 19:53:13Z",
"expirationDate": "2025-07-19 21:12:48Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
},
"8c53250a171412b84dedcbb22cdab9ec365d9b52d74b09c070097fff45372de0": {
"signature": "8c53250a171412b84dedcbb22cdab9ec365d9b52d74b09c070097fff45372de0",
"alternativeSignatures": [
"314267784b0ea867006e00b809a93498fae3264e42d1a3a7745ab13180a5b6ef"
],
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-02-04 06:16:33Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"a6a58d971da858f4af219672cef73ffd0aacc47f1e2c12b8b44a428e1330d3de": {
"signature": "a6a58d971da858f4af219672cef73ffd0aacc47f1e2c12b8b44a428e1330d3de",
"alternativeSignatures": [
"4e40f2f1683f0bf2245f35d0ebbcf2f446274d84b1db09d8e76ddfdcad5d4479"
],
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-02-04 06:16:33Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"90e0f060e01e4a55620f609ac3241b62e8f54a059e9f4d292e93a4305fd3c39e": {
"signature": "90e0f060e01e4a55620f609ac3241b62e8f54a059e9f4d292e93a4305fd3c39e",
"alternativeSignatures": [
"377fe43ff8404d07f4a6ca763175004f360397ded6cf5d55b655646ada90e39c"
],
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-02-04 06:17:54Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"f36c3dc19566098a923877d16d6ebfcbd971f8fcd8210afb8f5558fb5ba1f203": {
"signature": "f36c3dc19566098a923877d16d6ebfcbd971f8fcd8210afb8f5558fb5ba1f203",
"alternativeSignatures": [
"1af1f475c1617701e3d7a8fd465916bcc60c3125b8807af5d47d49137d9d468c"
],
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-02-04 06:17:54Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"71193d108c53bb802f5c491276365bcff0645fb380be57288f3fbd6896166d3a": {
"signature": "71193d108c53bb802f5c491276365bcff0645fb380be57288f3fbd6896166d3a",
"alternativeSignatures": [
"420cae2e6e34b93d7b74fc1ffddfdf23b57650ae989d838bb2d67f28e4e1db0e"
],
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-02-04 07:11:19Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"444c302f49bdedcafe772322a09727b2279e3265d99deb2e307defeae3ef200b": {
"signature": "444c302f49bdedcafe772322a09727b2279e3265d99deb2e307defeae3ef200b",
"alternativeSignatures": [
"4ff6ccbdb0745d43d3b61f82fb2f4d8a64fe9787525df81a6d7b825e79282085"
],
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-02-04 07:11:19Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"4670c7c096a69ca428429ffa1f5250aac9f2e07beac0ffe587ffb37bdb1da4d4": {
"signature": "4670c7c096a69ca428429ffa1f5250aac9f2e07beac0ffe587ffb37bdb1da4d4",
"alternativeSignatures": [
"7cead96cb508ab6e37e27bcc0f8b7ed8d0761b77f4793958c46c5ff3892ab1b6"
],
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2009",
"createdDate": "2025-02-04 07:13:22Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
},
"a359b4a5ed2378a73f3bba93e3fb1c595db7423c3082635d12d101bbeb0a51b8": {
"signature": "a359b4a5ed2378a73f3bba93e3fb1c595db7423c3082635d12d101bbeb0a51b8",
"alternativeSignatures": [
"125b52a21ef619a95e695085deb9492280bcf2c1decdd5e87e6416af5982d02d"
],
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.98.0-insider.exe",
"memberOf": [
"default"
],
"tool": "binskim",
"ruleId": "BA2018",
"createdDate": "2025-02-04 07:13:22Z",
"expirationDate": "2025-07-24 07:25:17Z",
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
}
}
}
================================================
FILE: .config/guardian/.gdnsuppress
================================================
{
"hydrated": false,
"properties": {
"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",
"suppressionSets": {
"default": {
"name": "default",
"createdDate": "2025-03-17 11:52:32Z",
"lastUpdatedDate": "2025-03-17 11:52:32Z"
}
},
"results": {
"216e2ac9cb596796224b47799f656570a01fa0d9b5f935608b47d15ab613c8e8": {
"signature": "216e2ac9cb596796224b47799f656570a01fa0d9b5f935608b47d15ab613c8e8",
"alternativeSignatures": [
"07746898f43afab7cc50931b33154c2d9e1a35f82a649dbe8aecf785b3d5a813"
],
"memberOf": [
"default"
],
"createdDate": "2025-03-17 11:52:32Z"
},
"77797a3e44634bb2994bd13ccc95ff4575bba474585dbd2cf3068a1c16bc0624": {
"signature": "77797a3e44634bb2994bd13ccc95ff4575bba474585dbd2cf3068a1c16bc0624",
"alternativeSignatures": [
"4a6cb67bd4b401e9669c13a2162660aaefc0a94a4122e5b50c198414db545672"
],
"memberOf": [
"default"
],
"createdDate": "2025-03-17 11:52:32Z"
},
"30418bcc5269eaeb2832a2404465784431d4e72a2af332320c2b1db4768902ad": {
"signature": "30418bcc5269eaeb2832a2404465784431d4e72a2af332320c2b1db4768902ad",
"alternativeSignatures": [
"b7b9eb974d7d3a4ae14df8695ca5a62592c8c9d20b7eda70a6535d50cbda3e7f"
],
"memberOf": [
"default"
],
"createdDate": "2025-03-17 11:52:32Z"
}
}
}
================================================
FILE: .configurations/configuration.dsc.yaml
================================================
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
# Reference: https://github.com/microsoft/vscode/wiki/How-to-Contribute
properties:
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Install Git
allowPrerelease: true
settings:
id: Git.Git
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: npm
directives:
description: Install NodeJS version 20
allowPrerelease: true
settings:
id: OpenJS.NodeJS.LTS
version: "20.14.0"
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Install Python 3.10
allowPrerelease: true
settings:
id: Python.Python.3.10
source: winget
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vsPackage
directives:
description: Install Visual Studio 2022 (any edition is OK)
allowPrerelease: true
settings:
id: Microsoft.VisualStudio.2022.BuildTools
source: winget
- resource: Microsoft.VisualStudio.DSC/VSComponents
dependsOn:
- vsPackage
directives:
description: Install required VS workloads
allowPrerelease: true
settings:
productId: Microsoft.VisualStudio.Product.BuildTools
channelId: VisualStudio.17.Release
includeRecommended: true
components:
- Microsoft.VisualStudio.Workload.VCTools
- resource: NpmDsc/NpmInstall
dependsOn:
- npm
directives:
description: Install dependencies
allowPrerelease: true
settings:
PackageDirectory: '${WinGetConfigRoot}\..\'
configurationVersion: 0.2.0
================================================
FILE: .devcontainer/Dockerfile
================================================
FROM mcr.microsoft.com/devcontainers/typescript-node:20-bookworm
ADD install-vscode.sh /root/
RUN /root/install-vscode.sh
RUN git config --system codespaces-theme.hide-status 1
USER node
RUN npm install -g node-gyp
RUN NPM_CACHE="$(npm config get cache)" && rm -rf "$NPM_CACHE" && ln -s /vscode-dev/npm-cache "$NPM_CACHE"
RUN echo 'export DISPLAY="${DISPLAY:-:1}"' | tee -a ~/.bashrc >> ~/.zshrc
USER root
CMD chown node:node /vscode-dev && sudo -u node mkdir -p /vscode-dev/npm-cache && sleep inf
================================================
FILE: .devcontainer/README.md
================================================
# Code - OSS Development Container
[](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode)
This repository includes configuration for a development container for working with Code - OSS in a local container or using [GitHub Codespaces](https://github.com/features/codespaces).
> **Tip:** The default VNC password is `vscode`. The VNC server runs on port `5901` and a web client is available on port `6080`.
## Quick start - local
If you already have VS Code and Docker installed, you can click the badge above or [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode) to get started. Clicking these links will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.
1. Install Docker Desktop or Docker for Linux on your local machine. (See [docs](https://aka.ms/vscode-remote/containers/getting-started) for additional details.)
2. **Important**: Docker needs at least **4 Cores and 8 GB of RAM** to run a full build with **9 GB of RAM** being recommended. If you are on macOS, or are using the old Hyper-V engine for Windows, update these values for Docker Desktop by right-clicking on the Docker status bar item and going to **Preferences/Settings > Resources > Advanced**.
> **Note:** The [Resource Monitor](https://marketplace.visualstudio.com/items?itemName=mutantdino.resourcemonitor) extension is included in the container so you can keep an eye on CPU/Memory in the status bar.
3. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the [Dev Containers](https://aka.ms/vscode-remote/download/containers) extension.

> **Note:** The Dev Containers extension requires the Visual Studio Code distribution of Code - OSS. See the [FAQ](https://aka.ms/vscode-remote/faq/license) for details.
4. Press Ctrl/Cmd + Shift + P or F1 and select **Dev Containers: Clone Repository in Container Volume...**.
> **Tip:** While you can use your local source tree instead, operations like `npm i` can be slow on macOS or when using the Hyper-V engine on Windows. We recommend using the WSL filesystem on Windows or the "clone repository in container" approach on Windows and macOS instead since it uses "named volume" rather than the local filesystem.
5. Type `https://github.com/microsoft/vscode` (or a branch or PR URL) in the input box and press Enter.
6. After the container is running:
1. If you have the `DISPLAY` or `WAYLAND_DISPLAY` environment variables set locally (or in WSL on Windows), desktop apps in the container will be shown in local windows.
2. If these are not set, open a web browser and go to [http://localhost:6080](http://localhost:6080), or use a [VNC Viewer][def] to connect to `localhost:5901` and enter `vscode` as the password. Anything you start in VS Code, or the integrated terminal, will appear here.
Next: **[Try it out!](#try-it)**
## Quick start - GitHub Codespaces
1. From the [microsoft/vscode GitHub repository](https://github.com/microsoft/vscode), click on the **Code** dropdown, select **Open with Codespaces**, and then click on **New codespace**. If prompted, select the **Standard** machine size (which is also the default).
> **Note:** You will not see these options within GitHub if you are not in the Codespaces beta.
2. After the codespace is up and running in your browser, press Ctrl/Cmd + Shift + P or F1 and select **Ports: Focus on Ports View**.
3. You should see **VNC web client (6080)** under in the list of ports. Select the line and click on the globe icon to open it in a browser tab.
> **Tip:** If you do not see the port, Ctrl/Cmd + Shift + P or F1, select **Forward a Port** and enter port `6080`.
4. In the new tab, you should see noVNC. Click **Connect** and enter `vscode` as the password.
Anything you start in VS Code, or the integrated terminal, will appear here.
Next: **[Try it out!](#try-it)**
### Using VS Code with GitHub Codespaces
You may see improved VNC responsiveness when accessing a codespace from VS Code client since you can use a [VNC Viewer][def]. Here's how to do it.
1. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the [GitHub Codespaces extension](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces).
> **Note:** The GitHub Codespaces extension requires the Visual Studio Code distribution of Code - OSS.
2. After the VS Code is up and running, press Ctrl/Cmd + Shift + P or F1, choose **Codespaces: Create New Codespace**, and use the following settings:
- `microsoft/vscode` for the repository.
- Select any branch (e.g. **main**) - you can select a different one later.
- Choose **Standard** (4-core, 8GB) as the size.
3. After you have connected to the codespace, you can use a [VNC Viewer][def] to connect to `localhost:5901` and enter `vscode` as the password.
> **Tip:** You may also need change your VNC client's **Picture Quality** setting to **High** to get a full color desktop.
4. Anything you start in VS Code, or the integrated terminal, will appear here.
Next: **[Try it out!](#try-it)**
## Try it
This container uses the [Fluxbox](http://fluxbox.org/) window manager to keep things lean. **Right-click on the desktop** to see menu options. It works with GNOME and GTK applications, so other tools can be installed if needed.
> **Note:** You can also set the resolution from the command line by typing `set-resolution`.
To start working with Code - OSS, follow these steps:
1. In your local VS Code client, open a terminal (Ctrl/Cmd + Shift + \`) and type the following commands:
```bash
npm i
bash scripts/code.sh
```
2. After the build is complete, open a web browser or a [VNC Viewer][def] to connect to the desktop environment as described in the quick start and enter `vscode` as the password.
3. You should now see Code - OSS!
Next, let's try debugging.
1. Shut down Code - OSS by clicking the box in the upper right corner of the Code - OSS window through your browser or VNC viewer.
2. Go to your local VS Code client, and use the **Run / Debug** view to launch the **VS Code** configuration. (Typically the default, so you can likely just press F5).
> **Note:** If launching times out, you can increase the value of `timeout` in the "VS Code", "Attach Main Process", "Attach Extension Host", and "Attach to Shared Process" configurations in [launch.json](../../.vscode/launch.json). However, running `./scripts/code.sh` first will set up Electron which will usually solve timeout issues.
3. After a bit, Code - OSS will appear with the debugger attached!
Enjoy!
### Notes
The container comes with VS Code Insiders installed. To run it from an Integrated Terminal use `VSCODE_IPC_HOOK_CLI= /usr/bin/code-insiders .`.
[def]: https://www.realvnc.com/en/connect/download/viewer/
================================================
FILE: .devcontainer/devcontainer-lock.json
================================================
{
"features": {
"ghcr.io/devcontainers/features/desktop-lite:1": {
"version": "1.0.8",
"resolved": "ghcr.io/devcontainers/features/desktop-lite@sha256:e7dc4d37ab9e3d6e7ebb221bac741f5bfe07dae47025399d038b17af2ed8ddb7",
"integrity": "sha256:e7dc4d37ab9e3d6e7ebb221bac741f5bfe07dae47025399d038b17af2ed8ddb7"
},
"ghcr.io/devcontainers/features/rust:1": {
"version": "1.1.3",
"resolved": "ghcr.io/devcontainers/features/rust@sha256:aba6f47303b197976902bf544c786b5efecc03c238ff593583e5e74dfa9c7ccb",
"integrity": "sha256:aba6f47303b197976902bf544c786b5efecc03c238ff593583e5e74dfa9c7ccb"
}
}
}
================================================
FILE: .devcontainer/devcontainer.json
================================================
{
"name": "Code - OSS",
"build": {
"dockerfile": "Dockerfile"
},
"features": {
"ghcr.io/devcontainers/features/desktop-lite:1": {},
"ghcr.io/devcontainers/features/rust:1": {}
},
"containerEnv": {
"DISPLAY": "" // Allow the Dev Containers extension to set DISPLAY, post-create.sh will add it back in ~/.bashrc and ~/.zshrc if not set.
},
"overrideCommand": false,
"privileged": true,
"mounts": [
{
"source": "vscode-dev",
"target": "/vscode-dev",
"type": "volume"
}
],
"postCreateCommand": "./.devcontainer/post-create.sh",
"customizations": {
"vscode": {
"settings": {
"resmon.show.battery": false,
"resmon.show.cpufreq": false
},
"extensions": [
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"GitHub.vscode-pull-request-github",
"ms-vscode.vscode-github-issue-notebooks",
"ms-vscode.vscode-selfhost-test-provider",
"mutantdino.resourcemonitor"
]
}
},
"forwardPorts": [6080, 5901],
"portsAttributes": {
"6080": {
"label": "VNC web client (noVNC)",
"onAutoForward": "silent"
},
"5901": {
"label": "VNC TCP port",
"onAutoForward": "silent"
}
},
"hostRequirements": {
"memory": "9gb"
}
}
================================================
FILE: .devcontainer/install-vscode.sh
================================================
#!/bin/sh
apt update
apt install -y wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
rm -f packages.microsoft.gpg
apt update
apt install -y code-insiders libsecret-1-dev libxkbfile-dev libkrb5-dev
================================================
FILE: .devcontainer/post-create.sh
================================================
#!/bin/sh
npm i
npm run electron
================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Tab indentation
[*]
indent_style = tab
trim_trailing_whitespace = true
# The indent size used in the `package.json` file cannot be changed
# https://github.com/npm/npm/pull/3180#issuecomment-16336516
[{*.yml,*.yaml,package.json}]
indent_style = space
indent_size = 2
================================================
FILE: .eslint-ignore
================================================
**/build/*/**/*.js
**/dist/**/*.js
**/extensions/**/*.d.ts
**/extensions/**/build/**
**/extensions/**/colorize-fixtures/**
**/extensions/css-language-features/server/test/pathCompletionFixtures/**
**/extensions/html-language-features/server/lib/jquery.d.ts
**/extensions/html-language-features/server/src/test/pathCompletionFixtures/**
**/extensions/ipynb/notebook-out/**
**/extensions/markdown-language-features/media/**
**/extensions/markdown-language-features/notebook-out/**
**/extensions/markdown-math/notebook-out/**
**/extensions/notebook-renderers/renderer-out/index.js
**/extensions/simple-browser/media/index.js
**/extensions/terminal-suggest/src/completions/upstream/**
**/extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts
**/extensions/terminal-suggest/src/shell/fishBuiltinsCache.ts
**/extensions/terminal-suggest/third_party/**
**/extensions/typescript-language-features/test-workspace/**
**/extensions/typescript-language-features/extension.webpack.config.js
**/extensions/typescript-language-features/extension-browser.webpack.config.js
**/extensions/typescript-language-features/package-manager/node-maintainer/**
**/extensions/vscode-api-tests/testWorkspace/**
**/extensions/vscode-api-tests/testWorkspace2/**
**/fixtures/**
**/node_modules/**
**/out-*/**/*.js
**/out-editor-*/**
**/out/**/*.js
**/src/**/dompurify.js
**/src/**/marked.js
**/src/**/semver.js
**/src/typings/**/*.d.ts
**/src/vs/*/**/*.d.ts
**/src/vs/base/test/common/filters.perf.data.js
**/src/vs/loader.js
**/test/unit/assert.js
**/test/automation/out/**
**/typings/**
**/.build/**
!.vscode
================================================
FILE: .eslint-plugin-local/code-amd-node-module.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';
import { join } from 'path';
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
amdX: 'Use `import type` for import declarations, use `amdX#importAMDNodeModule` for import expressions'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const modules = new Set();
try {
const { dependencies, optionalDependencies } = require(join(__dirname, '../package.json'));
const all = Object.keys(dependencies).concat(Object.keys(optionalDependencies));
for (const key of all) {
modules.add(key);
}
} catch (e) {
console.error(e);
throw e;
}
const checkImport = (node: any) => {
if (node.type !== 'Literal' || typeof node.value !== 'string') {
return;
}
if (node.parent.importKind === 'type') {
return;
}
if (!modules.has(node.value)) {
return;
}
context.report({
node,
messageId: 'amdX'
});
};
return {
['ImportExpression Literal']: checkImport,
['ImportDeclaration Literal']: checkImport
};
}
};
================================================
FILE: .eslint-plugin-local/code-declare-service-brand.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 DeclareServiceBrand implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
fixable: 'code',
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['PropertyDefinition[key.name="_serviceBrand"][value]']: (node: any) => {
return context.report({
node,
message: `The '_serviceBrand'-property should not have a value`,
fix: (fixer) => {
return fixer.replaceText(node, 'declare _serviceBrand: undefined;');
}
});
}
};
}
};
================================================
FILE: .eslint-plugin-local/code-ensure-no-disposables-leak-in-test.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';
import { Node } from 'estree';
export = new class EnsureNoDisposablesAreLeakedInTestSuite implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
type: 'problem',
messages: {
ensure: 'Suites should include a call to `ensureNoDisposablesAreLeakedInTestSuite()` to ensure no disposables are leaked in tests.'
},
fixable: 'code',
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const config = <{ exclude: string[] }>context.options[0];
const needle = context.getFilename().replace(/\\/g, '/');
if (config.exclude.some((e) => needle.endsWith(e))) {
return {};
}
return {
[`Program > ExpressionStatement > CallExpression[callee.name='suite']`]: (node: Node) => {
const src = context.getSourceCode().getText(node);
if (!src.includes('ensureNoDisposablesAreLeakedInTestSuite(')) {
context.report({
node,
messageId: 'ensure',
fix: (fixer) => {
const updatedSrc = src.replace(/(suite\(.*\n)/, '$1\n\tensureNoDisposablesAreLeakedInTestSuite();\n');
return fixer.replaceText(node, updatedSrc);
}
});
}
},
};
}
};
================================================
FILE: .eslint-plugin-local/code-import-patterns.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';
import { TSESTree } from '@typescript-eslint/utils';
import * as path from 'path';
import minimatch from 'minimatch';
import { createImportRuleListener } from './utils';
const REPO_ROOT = path.normalize(path.join(__dirname, '../'));
interface ConditionalPattern {
when?: 'hasBrowser' | 'hasNode' | 'hasElectron' | 'test';
pattern: string;
}
interface RawImportPatternsConfig {
target: string;
layer?: 'common' | 'worker' | 'browser' | 'electron-sandbox' | 'node' | 'electron-utility' | 'electron-main';
test?: boolean;
restrictions: string | (string | ConditionalPattern)[];
}
interface LayerAllowRule {
when: 'hasBrowser' | 'hasNode' | 'hasElectron' | 'test';
allow: string[];
}
type RawOption = RawImportPatternsConfig | LayerAllowRule;
function isLayerAllowRule(option: RawOption): option is LayerAllowRule {
return !!((option).when && (option).allow);
}
interface ImportPatternsConfig {
target: string;
restrictions: string[];
}
export = new class implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
badImport: 'Imports violates \'{{restrictions}}\' restrictions. See https://github.com/microsoft/vscode/wiki/Source-Code-Organization',
badFilename: 'Missing definition in `code-import-patterns` for this file. Define rules at https://github.com/microsoft/vscode/blob/main/eslint.config.js',
badAbsolute: 'Imports have to be relative to support ESM',
badExtension: 'Imports have to end with `.js` or `.css` to support ESM',
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const options = context.options;
const configs = this._processOptions(options);
const relativeFilename = getRelativeFilename(context);
for (const config of configs) {
if (minimatch(relativeFilename, config.target)) {
return createImportRuleListener((node, value) => this._checkImport(context, config, node, value));
}
}
context.report({
loc: { line: 1, column: 0 },
messageId: 'badFilename'
});
return {};
}
private _optionsCache = new WeakMap();
private _processOptions(options: RawOption[]): ImportPatternsConfig[] {
if (this._optionsCache.has(options)) {
return this._optionsCache.get(options)!;
}
type Layer = 'common' | 'worker' | 'browser' | 'electron-sandbox' | 'node' | 'electron-utility' | 'electron-main';
interface ILayerRule {
layer: Layer;
deps: string;
isBrowser?: boolean;
isNode?: boolean;
isElectron?: boolean;
}
function orSegment(variants: Layer[]): string {
return (variants.length === 1 ? variants[0] : `{${variants.join(',')}}`);
}
const layerRules: ILayerRule[] = [
{ layer: 'common', deps: orSegment(['common']) },
{ layer: 'worker', deps: orSegment(['common', 'worker']) },
{ layer: 'browser', deps: orSegment(['common', 'browser']), isBrowser: true },
{ layer: 'electron-sandbox', deps: orSegment(['common', 'browser', 'electron-sandbox']), isBrowser: true },
{ layer: 'node', deps: orSegment(['common', 'node']), isNode: true },
{ layer: 'electron-utility', deps: orSegment(['common', 'node', 'electron-utility']), isNode: true, isElectron: true },
{ layer: 'electron-main', deps: orSegment(['common', 'node', 'electron-utility', 'electron-main']), isNode: true, isElectron: true },
];
let browserAllow: string[] = [];
let nodeAllow: string[] = [];
let electronAllow: string[] = [];
let testAllow: string[] = [];
for (const option of options) {
if (isLayerAllowRule(option)) {
if (option.when === 'hasBrowser') {
browserAllow = option.allow.slice(0);
} else if (option.when === 'hasNode') {
nodeAllow = option.allow.slice(0);
} else if (option.when === 'hasElectron') {
electronAllow = option.allow.slice(0);
} else if (option.when === 'test') {
testAllow = option.allow.slice(0);
}
}
}
function findLayer(layer: Layer): ILayerRule | null {
for (const layerRule of layerRules) {
if (layerRule.layer === layer) {
return layerRule;
}
}
return null;
}
function generateConfig(layerRule: ILayerRule, target: string, rawRestrictions: (string | ConditionalPattern)[]): [ImportPatternsConfig, ImportPatternsConfig] {
const restrictions: string[] = [];
const testRestrictions: string[] = [...testAllow];
if (layerRule.isBrowser) {
restrictions.push(...browserAllow);
}
if (layerRule.isNode) {
restrictions.push(...nodeAllow);
}
if (layerRule.isElectron) {
restrictions.push(...electronAllow);
}
for (const rawRestriction of rawRestrictions) {
let importPattern: string;
let when: 'hasBrowser' | 'hasNode' | 'hasElectron' | 'test' | undefined = undefined;
if (typeof rawRestriction === 'string') {
importPattern = rawRestriction;
} else {
importPattern = rawRestriction.pattern;
when = rawRestriction.when;
}
if (typeof when === 'undefined'
|| (when === 'hasBrowser' && layerRule.isBrowser)
|| (when === 'hasNode' && layerRule.isNode)
|| (when === 'hasElectron' && layerRule.isElectron)
) {
restrictions.push(importPattern.replace(/\/\~$/, `/${layerRule.deps}/**`));
testRestrictions.push(importPattern.replace(/\/\~$/, `/test/${layerRule.deps}/**`));
} else if (when === 'test') {
testRestrictions.push(importPattern.replace(/\/\~$/, `/${layerRule.deps}/**`));
testRestrictions.push(importPattern.replace(/\/\~$/, `/test/${layerRule.deps}/**`));
}
}
testRestrictions.push(...restrictions);
return [
{
target: target.replace(/\/\~$/, `/${layerRule.layer}/**`),
restrictions: restrictions
},
{
target: target.replace(/\/\~$/, `/test/${layerRule.layer}/**`),
restrictions: testRestrictions
}
];
}
const configs: ImportPatternsConfig[] = [];
for (const option of options) {
if (isLayerAllowRule(option)) {
continue;
}
const target = option.target;
const targetIsVS = /^src\/vs\//.test(target);
const restrictions = (typeof option.restrictions === 'string' ? [option.restrictions] : option.restrictions).slice(0);
if (targetIsVS) {
// Always add "vs/nls" and "vs/amdX"
restrictions.push('vs/nls.js');
restrictions.push('vs/amdX.js'); // TODO@jrieken remove after ESM is real
}
if (targetIsVS && option.layer) {
// single layer => simple substitution for /~
const layerRule = findLayer(option.layer);
if (layerRule) {
const [config, testConfig] = generateConfig(layerRule, target, restrictions);
if (option.test) {
configs.push(testConfig);
} else {
configs.push(config);
}
}
} else if (targetIsVS && /\/\~$/.test(target)) {
// generate all layers
for (const layerRule of layerRules) {
const [config, testConfig] = generateConfig(layerRule, target, restrictions);
configs.push(config);
configs.push(testConfig);
}
} else {
configs.push({ target, restrictions: restrictions.filter(r => typeof r === 'string') });
}
}
this._optionsCache.set(options, configs);
return configs;
}
private _checkImport(context: eslint.Rule.RuleContext, config: ImportPatternsConfig, node: TSESTree.Node, importPath: string) {
const targetIsVS = /^src\/vs\//.test(getRelativeFilename(context));
if (targetIsVS) {
// ESM: check for import ending with ".js" or ".css"
if (importPath[0] === '.' && !importPath.endsWith('.js') && !importPath.endsWith('.css')) {
context.report({
loc: node.loc,
messageId: 'badExtension',
});
}
// check for import being relative
if (importPath.startsWith('vs/')) {
context.report({
loc: node.loc,
messageId: 'badAbsolute',
});
}
}
// resolve relative paths
if (importPath[0] === '.') {
const relativeFilename = getRelativeFilename(context);
importPath = path.posix.join(path.posix.dirname(relativeFilename), importPath);
if (/^src\/vs\//.test(importPath)) {
// resolve using base url
importPath = importPath.substring('src/'.length);
}
}
const restrictions = config.restrictions;
let matched = false;
for (const pattern of restrictions) {
if (minimatch(importPath, pattern)) {
matched = true;
break;
}
}
if (!matched) {
// None of the restrictions matched
context.report({
loc: node.loc,
messageId: 'badImport',
data: {
restrictions: restrictions.join(' or ')
}
});
}
}
};
/**
* Returns the filename relative to the project root and using `/` as separators
*/
function getRelativeFilename(context: eslint.Rule.RuleContext): string {
const filename = path.normalize(context.getFilename());
return filename.substring(REPO_ROOT.length).replace(/\\/g, '/');
}
================================================
FILE: .eslint-plugin-local/code-layering.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';
import { join, dirname } from 'path';
import { createImportRuleListener } from './utils';
type Config = {
allowed: Set;
disallowed: Set;
};
export = new class implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
layerbreaker: 'Bad layering. You are not allowed to access {{from}} from here, allowed layers are: [{{allowed}}]'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
},
schema: [
{
type: 'object',
additionalProperties: {
type: 'array',
items: {
type: 'string'
}
}
}
]
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const fileDirname = dirname(context.getFilename());
const parts = fileDirname.split(/\\|\//);
const ruleArgs = >context.options[0];
let config: Config | undefined;
for (let i = parts.length - 1; i >= 0; i--) {
if (ruleArgs[parts[i]]) {
config = {
allowed: new Set(ruleArgs[parts[i]]).add(parts[i]),
disallowed: new Set()
};
Object.keys(ruleArgs).forEach(key => {
if (!config!.allowed.has(key)) {
config!.disallowed.add(key);
}
});
break;
}
}
if (!config) {
// nothing
return {};
}
return createImportRuleListener((node, path) => {
if (path[0] === '.') {
path = join(dirname(context.getFilename()), path);
}
const parts = dirname(path).split(/\\|\//);
for (let i = parts.length - 1; i >= 0; i--) {
const part = parts[i];
if (config!.allowed.has(part)) {
// GOOD - same layer
break;
}
if (config!.disallowed.has(part)) {
// BAD - wrong layer
context.report({
loc: node.loc,
messageId: 'layerbreaker',
data: {
from: part,
allowed: [...config!.allowed.keys()].join(', ')
}
});
break;
}
}
});
}
};
================================================
FILE: .eslint-plugin-local/code-limited-top-functions.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';
import { dirname, relative } from 'path';
import minimatch from 'minimatch';
export = new class implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
layerbreaker: 'You are only allowed to define limited top level functions.'
},
schema: {
type: 'array',
items: {
type: 'object',
additionalProperties: {
type: 'array',
items: {
type: 'string'
}
}
}
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
let fileRelativePath = relative(dirname(__dirname), context.getFilename());
if (!fileRelativePath.endsWith('/')) {
fileRelativePath += '/';
}
const ruleArgs = >context.options[0];
const matchingKey = Object.keys(ruleArgs).find(key => fileRelativePath.startsWith(key) || minimatch(fileRelativePath, key));
if (!matchingKey) {
// nothing
return {};
}
const restrictedFunctions = ruleArgs[matchingKey];
return {
FunctionDeclaration: (node: any) => {
const isTopLevel = node.parent.type === 'Program';
const functionName = node.id.name;
if (isTopLevel && !restrictedFunctions.includes(node.id.name)) {
context.report({
node,
message: `Top-level function '${functionName}' is restricted in this file. Allowed functions are: ${restrictedFunctions.join(', ')}.`
});
}
},
ExportNamedDeclaration(node: any) {
if (node.declaration && node.declaration.type === 'FunctionDeclaration') {
const functionName = node.declaration.id.name;
const isTopLevel = node.parent.type === 'Program';
if (isTopLevel && !restrictedFunctions.includes(node.declaration.id.name)) {
context.report({
node,
message: `Top-level function '${functionName}' is restricted in this file. Allowed functions are: ${restrictedFunctions.join(', ')}.`
});
}
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/code-must-use-result.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';
import { TSESTree } from '@typescript-eslint/utils';
const VALID_USES = new Set([
TSESTree.AST_NODE_TYPES.AwaitExpression,
TSESTree.AST_NODE_TYPES.VariableDeclarator,
]);
export = 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 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)) {
context.report({ node, message });
}
};
}
}
return listener;
}
};
================================================
FILE: .eslint-plugin-local/code-must-use-super-dispose.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 NoAsyncSuite implements eslint.Rule.RuleModule {
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
function doesCallSuperDispose(node: any) {
if (!node.override) {
return;
}
const body = context.getSourceCode().getText(node);
if (body.includes('super.dispose')) {
return;
}
context.report({
node,
message: 'dispose() should call super.dispose()'
});
}
return {
['MethodDefinition[override][key.name="dispose"]']: doesCallSuperDispose,
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-dangerous-type-assertions.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';
import { TSESTree } from '@typescript-eslint/utils';
export = 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;
const parent = objectNode.parent as TSESTree.TSTypeAssertion | TSESTree.TSAsExpression;
if (
// Allow `as const` assertions
(parent.typeAnnotation.type === 'TSTypeReference' && parent.typeAnnotation.typeName.type === 'Identifier' && parent.typeAnnotation.typeName.name === 'const')
// For also now still allow `any` casts
|| (parent.typeAnnotation.type === 'TSAnyKeyword')
) {
return;
}
context.report({
node,
message: `Don't use type assertions for creating objects as this can hide type errors.`
});
},
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-global-document-listener.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 NoGlobalDocumentListener implements eslint.Rule.RuleModule {
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
CallExpression(node: any) {
if (
(
node.callee.name === 'addDisposableListener' ||
node.callee.property?.name === 'addDisposableListener'
) &&
node.arguments.length > 0 &&
node.arguments[0].type === 'Identifier' &&
node.arguments[0].name === 'document'
) {
context.report({
node,
message: 'Use .document to support multi-window scenarios. Resolve targetWindow with DOM.getWindow(element) or DOM.getActiveWindow() or use the predefined mainWindow constant.',
});
}
},
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-native-private.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 ApiProviderNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
slow: 'Native private fields are much slower and should only be used when needed. Ignore this warning if you know what you are doing, use compile-time private otherwise. See https://github.com/microsoft/vscode/issues/185991#issuecomment-1614468158 for details',
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['PropertyDefinition PrivateIdentifier']: (node: any) => {
context.report({
node,
messageId: 'slow'
});
},
['MethodDefinition PrivateIdentifier']: (node: any) => {
context.report({
node,
messageId: 'slow'
});
}
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-nls-in-standalone-editor.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';
import { join } from 'path';
import { createImportRuleListener } from './utils';
export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const fileName = context.getFilename();
if (
/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)editor.worker.start/.test(fileName)
) {
return createImportRuleListener((node, path) => {
// resolve relative paths
if (path[0] === '.') {
path = join(context.getFilename(), path);
}
if (
/vs(\/|\\)nls/.test(path)
) {
context.report({
loc: node.loc,
messageId: 'noNls'
});
}
});
}
return {};
}
};
================================================
FILE: .eslint-plugin-local/code-no-potentially-unsafe-disposables.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';
/**
* 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 {
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
function checkVariableDeclaration(inNode: any) {
context.report({
node: inNode,
message: `Use const for 'DisposableStore' to avoid leaks by accidental reassignment.`
});
}
function checkProperty(inNode: any) {
context.report({
node: inNode,
message: `Use readonly for DisposableStore/MutableDisposable to avoid leaks through accidental reassignment.`
});
}
return {
'VariableDeclaration[kind!="const"] NewExpression[callee.name="DisposableStore"]': checkVariableDeclaration,
'PropertyDefinition[readonly!=true][typeAnnotation.typeAnnotation.typeName.name=/DisposableStore|MutableDisposable/]': checkProperty,
'PropertyDefinition[readonly!=true] NewExpression[callee.name=/DisposableStore|MutableDisposable/]': checkProperty,
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-runtime-import.ts
================================================
/*---------------------------------------------------------------------------------------------
* 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/typescript-estree';
import * as eslint from 'eslint';
import { dirname, join, relative } from 'path';
import minimatch from 'minimatch';
import { createImportRuleListener } from './utils';
export = new class implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
layerbreaker: 'You are only allowed to import {{import}} from here using `import type ...`.'
},
schema: {
type: 'array',
items: {
type: 'object',
additionalProperties: {
type: 'array',
items: {
type: 'string'
}
}
}
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
let fileRelativePath = relative(dirname(__dirname), context.getFilename());
if (!fileRelativePath.endsWith('/')) {
fileRelativePath += '/';
}
const ruleArgs = >context.options[0];
const matchingKey = Object.keys(ruleArgs).find(key => fileRelativePath.startsWith(key) || minimatch(fileRelativePath, key));
if (!matchingKey) {
// nothing
return {};
}
const restrictedImports = ruleArgs[matchingKey];
return createImportRuleListener((node, path) => {
if (path[0] === '.') {
path = join(dirname(context.getFilename()), path);
}
if ((
restrictedImports.includes(path) || restrictedImports.some(restriction => minimatch(path, restriction))
) && !(
(node.parent?.type === TSESTree.AST_NODE_TYPES.ImportDeclaration && node.parent.importKind === 'type') ||
(node.parent && 'exportKind' in node.parent && node.parent.exportKind === 'type'))) { // the export could be multiple types
context.report({
loc: node.parent!.loc,
messageId: 'layerbreaker',
data: {
import: path
}
});
}
});
}
};
================================================
FILE: .eslint-plugin-local/code-no-standalone-editor.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';
import { join } from 'path';
import { createImportRuleListener } from './utils';
export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
badImport: 'Not allowed to import standalone editor modules.'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
if (/vs(\/|\\)editor/.test(context.getFilename())) {
// the vs/editor folder is allowed to use the standalone editor
return {};
}
return createImportRuleListener((node, path) => {
// resolve relative paths
if (path[0] === '.') {
path = join(context.getFilename(), path);
}
if (
/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path)
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path)
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(path)
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(path)
|| /vs(\/|\\)editor(\/|\\)editor.worker.start/.test(path)
) {
context.report({
loc: node.loc,
messageId: 'badImport'
});
}
});
}
};
================================================
FILE: .eslint-plugin-local/code-no-static-self-ref.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';
import { TSESTree } from '@typescript-eslint/utils';
/**
* WORKAROUND for https://github.com/evanw/esbuild/issues/3823
*/
export = new class implements eslint.Rule.RuleModule {
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
function checkProperty(inNode: any) {
const classDeclaration = context.sourceCode.getAncestors(inNode).find(node => node.type === 'ClassDeclaration');
const propertyDefinition = inNode;
if (!classDeclaration || !classDeclaration.id?.name) {
return;
}
if (!propertyDefinition.value) {
return;
}
const classCtor = classDeclaration.body.body.find(node => node.type === 'MethodDefinition' && node.kind === 'constructor');
if (!classCtor) {
return;
}
const name = classDeclaration.id.name;
const valueText = context.sourceCode.getText(propertyDefinition.value);
if (valueText.includes(name + '.')) {
if (classCtor.value?.type === 'FunctionExpression' && !classCtor.value.params.find((param: any) => param.type === 'TSParameterProperty' && param.decorators?.length > 0)) {
return;
}
context.report({
loc: propertyDefinition.value.loc,
message: `Static properties in decorated classes should not reference the class they are defined in. Use 'this' instead. This is a workaround for https://github.com/evanw/esbuild/issues/3823.`
});
}
}
return {
'PropertyDefinition[static=true]': checkProperty,
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-test-async-suite.ts
================================================
/*---------------------------------------------------------------------------------------------
* 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';
function isCallExpression(node: TSESTree.Node): node is TSESTree.CallExpression {
return node.type === 'CallExpression';
}
function isFunctionExpression(node: TSESTree.Node): node is TSESTree.FunctionExpression {
return node.type.includes('FunctionExpression');
}
export = 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) {
return context.report({
node: node as any,
message: 'suite factory function should never be async'
});
}
}
return {
['CallExpression[callee.name=/suite$/][arguments]']: hasAsyncSuite,
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-test-only.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 NoTestOnly implements eslint.Rule.RuleModule {
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['MemberExpression[object.name=/^(test|suite)$/][property.name="only"]']: (node: any) => {
return context.report({
node,
message: 'only is a dev-time tool and CANNOT be pushed'
});
}
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-unexternalized-strings.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';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils';
function isStringLiteral(node: TSESTree.Node | null | undefined): node is TSESTree.StringLiteral {
return !!node && node.type === AST_NODE_TYPES.Literal && typeof node.value === 'string';
}
function isDoubleQuoted(node: TSESTree.StringLiteral): boolean {
return node.raw[0] === '"' && node.raw[node.raw.length - 1] === '"';
}
export = new class NoUnexternalizedStrings implements eslint.Rule.RuleModule {
private static _rNlsKeys = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/;
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
doubleQuoted: 'Only use double-quoted strings for externalized strings.',
badKey: 'The key \'{{key}}\' doesn\'t conform to a valid localize identifier.',
duplicateKey: 'Duplicate key \'{{key}}\' with different message value.',
badMessage: 'Message argument to \'{{message}}\' must be a string literal.'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const externalizedStringLiterals = new Map();
const doubleQuotedStringLiterals = new Set();
function collectDoubleQuotedStrings(node: TSESTree.Literal) {
if (isStringLiteral(node) && isDoubleQuoted(node)) {
doubleQuotedStringLiterals.add(node);
}
}
function visitLocalizeCall(node: TSESTree.CallExpression) {
// localize(key, message)
const [keyNode, messageNode] = (node).arguments;
// (1)
// extract key so that it can be checked later
let key: string | undefined;
if (isStringLiteral(keyNode)) {
doubleQuotedStringLiterals.delete(keyNode);
key = keyNode.value;
} else if (keyNode.type === AST_NODE_TYPES.ObjectExpression) {
for (const property of keyNode.properties) {
if (property.type === AST_NODE_TYPES.Property && !property.computed) {
if (property.key.type === AST_NODE_TYPES.Identifier && property.key.name === 'key') {
if (isStringLiteral(property.value)) {
doubleQuotedStringLiterals.delete(property.value);
key = property.value.value;
break;
}
}
}
}
}
if (typeof key === 'string') {
let array = externalizedStringLiterals.get(key);
if (!array) {
array = [];
externalizedStringLiterals.set(key, array);
}
array.push({ call: node, message: messageNode });
}
// (2)
// remove message-argument from doubleQuoted list and make
// sure it is a string-literal
doubleQuotedStringLiterals.delete(messageNode);
if (!isStringLiteral(messageNode)) {
context.report({
loc: messageNode.loc,
messageId: 'badMessage',
data: { message: context.getSourceCode().getText(node) }
});
}
}
function visitL10NCall(node: TSESTree.CallExpression) {
// localize(key, message)
const [messageNode] = (node).arguments;
// remove message-argument from doubleQuoted list and make
// sure it is a string-literal
if (isStringLiteral(messageNode)) {
doubleQuotedStringLiterals.delete(messageNode);
} else if (messageNode.type === AST_NODE_TYPES.ObjectExpression) {
for (const prop of messageNode.properties) {
if (prop.type === AST_NODE_TYPES.Property) {
if (prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === 'message') {
doubleQuotedStringLiterals.delete(prop.value);
break;
}
}
}
}
}
function reportBadStringsAndBadKeys() {
// (1)
// report all strings that are in double quotes
for (const node of doubleQuotedStringLiterals) {
context.report({ loc: node.loc, messageId: 'doubleQuoted' });
}
for (const [key, values] of externalizedStringLiterals) {
// (2)
// report all invalid NLS keys
if (!key.match(NoUnexternalizedStrings._rNlsKeys)) {
for (const value of values) {
context.report({ loc: value.call.loc, messageId: 'badKey', data: { key } });
}
}
// (2)
// report all invalid duplicates (same key, different message)
if (values.length > 1) {
for (let i = 1; i < values.length; i++) {
if (context.getSourceCode().getText(values[i - 1].message) !== context.getSourceCode().getText(values[i].message)) {
context.report({ loc: values[i].call.loc, messageId: 'duplicateKey', data: { key } });
}
}
}
}
}
return {
['Literal']: (node: any) => collectDoubleQuotedStrings(node),
['ExpressionStatement[directive] Literal:exit']: (node: any) => doubleQuotedStringLiterals.delete(node),
// localize(...)
['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize"]:exit']: (node: any) => visitLocalizeCall(node),
// localize2(...)
['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize2"]:exit']: (node: any) => visitLocalizeCall(node),
// vscode.l10n.t(...)
['CallExpression[callee.type="MemberExpression"][callee.object.property.name="l10n"][callee.property.name="t"]:exit']: (node: any) => visitL10NCall(node),
// l10n.t(...)
['CallExpression[callee.object.name="l10n"][callee.property.name="t"]:exit']: (node: any) => visitL10NCall(node),
['CallExpression[callee.name="localize"][arguments.length>=2]:exit']: (node: any) => visitLocalizeCall(node),
['CallExpression[callee.name="localize2"][arguments.length>=2]:exit']: (node: any) => visitLocalizeCall(node),
['Program:exit']: reportBadStringsAndBadKeys,
};
}
};
================================================
FILE: .eslint-plugin-local/code-no-unused-expressions.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// FORKED FROM https://github.com/eslint/eslint/blob/b23ad0d789a909baf8d7c41a35bc53df932eaf30/lib/rules/no-unused-expressions.js
// and added support for `OptionalCallExpression`, see https://github.com/facebook/create-react-app/issues/8107 and https://github.com/eslint/eslint/issues/12642
/**
* @fileoverview Flag expressions in statement position that do not side effect
* @author Michael Ficarra
*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/utils';
import * as ESTree from 'estree';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'disallow unused expressions',
category: 'Best Practices',
recommended: false,
url: 'https://eslint.org/docs/rules/no-unused-expressions'
},
schema: [
{
type: 'object',
properties: {
allowShortCircuit: {
type: 'boolean',
default: false
},
allowTernary: {
type: 'boolean',
default: false
},
allowTaggedTemplates: {
type: 'boolean',
default: false
}
},
additionalProperties: false
}
]
},
create(context: eslint.Rule.RuleContext) {
const config = context.options[0] || {},
allowShortCircuit = config.allowShortCircuit || false,
allowTernary = config.allowTernary || false,
allowTaggedTemplates = config.allowTaggedTemplates || false;
/**
* @param node any node
* @returns whether the given node structurally represents a directive
*/
function looksLikeDirective(node: TSESTree.Node): boolean {
return node.type === 'ExpressionStatement' &&
node.expression.type === 'Literal' && typeof node.expression.value === 'string';
}
/**
* @param predicate ([a] -> Boolean) the function used to make the determination
* @param list the input list
* @returns the leading sequence of members in the given list that pass the given predicate
*/
function takeWhile(predicate: (item: T) => boolean, list: T[]): T[] {
for (let i = 0; i < list.length; ++i) {
if (!predicate(list[i])) {
return list.slice(0, i);
}
}
return list.slice();
}
/**
* @param node a Program or BlockStatement node
* @returns the leading sequence of directive nodes in the given node's body
*/
function directives(node: TSESTree.Program | TSESTree.BlockStatement): TSESTree.Node[] {
return takeWhile(looksLikeDirective, node.body);
}
/**
* @param node any node
* @param ancestors the given node's ancestors
* @returns whether the given node is considered a directive in its current position
*/
function isDirective(node: TSESTree.Node, ancestors: TSESTree.Node[]): boolean {
const parent = ancestors[ancestors.length - 1],
grandparent = ancestors[ancestors.length - 2];
return (parent.type === 'Program' || parent.type === 'BlockStatement' &&
(/Function/u.test(grandparent.type))) &&
directives(parent).indexOf(node) >= 0;
}
/**
* Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags.
* @param node any node
* @returns whether the given node is a valid expression
*/
function isValidExpression(node: TSESTree.Node): boolean {
if (allowTernary) {
// Recursive check for ternary and logical expressions
if (node.type === 'ConditionalExpression') {
return isValidExpression(node.consequent) && isValidExpression(node.alternate);
}
}
if (allowShortCircuit) {
if (node.type === 'LogicalExpression') {
return isValidExpression(node.right);
}
}
if (allowTaggedTemplates && node.type === 'TaggedTemplateExpression') {
return true;
}
if (node.type === 'ExpressionStatement') {
return isValidExpression(node.expression);
}
return /^(?:Assignment|OptionalCall|Call|New|Update|Yield|Await|Chain)Expression$/u.test(node.type) ||
(node.type === 'UnaryExpression' && ['delete', 'void'].indexOf(node.operator) >= 0);
}
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}` });
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/code-parameter-properties-must-have-explicit-accessibility.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';
import { TSESTree } from '@typescript-eslint/utils';
/**
* 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 {
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
function check(inNode: any) {
const node: TSESTree.TSParameterProperty = inNode;
// For now, only apply to injected services
const firstDecorator = node.decorators?.at(0);
if (
firstDecorator?.expression.type !== 'Identifier'
|| !firstDecorator.expression.name.endsWith('Service')
) {
return;
}
if (!node.accessibility) {
context.report({
node: inNode,
message: 'Parameter properties must have an explicit access modifier.'
});
}
}
return {
['TSParameterProperty']: check,
};
}
};
================================================
FILE: .eslint-plugin-local/code-translation-remind.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';
import { TSESTree } from '@typescript-eslint/utils';
import { readFileSync } from 'fs';
import { createImportRuleListener } from './utils';
export = new class TranslationRemind implements eslint.Rule.RuleModule {
private static NLS_MODULE = 'vs/nls';
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return createImportRuleListener((node, path) => this._checkImport(context, node, path));
}
private _checkImport(context: eslint.Rule.RuleContext, node: TSESTree.Node, path: string) {
if (path !== TranslationRemind.NLS_MODULE) {
return;
}
const currentFile = context.getFilename();
const matchService = currentFile.match(/vs\/workbench\/services\/\w+/);
const matchPart = currentFile.match(/vs\/workbench\/contrib\/\w+/);
if (!matchService && !matchPart) {
return;
}
const resource = matchService ? matchService[0] : matchPart![0];
let resourceDefined = false;
let json;
try {
json = readFileSync('./build/lib/i18n.resources.json', 'utf8');
} catch (e) {
console.error('[translation-remind rule]: File with resources to pull from Transifex was not found. Aborting translation resource check for newly defined workbench part/service.');
return;
}
const workbenchResources = JSON.parse(json).workbench;
workbenchResources.forEach((existingResource: any) => {
if (existingResource.name === resource) {
resourceDefined = true;
return;
}
});
if (!resourceDefined) {
context.report({
loc: node.loc,
messageId: 'missing',
data: { resource }
});
}
}
};
================================================
FILE: .eslint-plugin-local/index.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const glob = require('glob');
const path = require('path');
require('ts-node').register({ experimentalResolver: true, transpileOnly: true });
// Re-export all .ts files as rules
const rules = {};
glob.sync(`${__dirname}/*.ts`).forEach((file) => {
rules[path.basename(file, '.ts')] = require(file);
});
exports.rules = rules;
================================================
FILE: .eslint-plugin-local/package.json
================================================
{
"type": "commonjs"
}
================================================
FILE: .eslint-plugin-local/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es2020",
"lib": [
"ES2020"
],
"module": "commonjs",
"esModuleInterop": true,
"alwaysStrict": true,
"allowJs": true,
"strict": true,
"exactOptionalPropertyTypes": false,
"useUnknownInCatchVariables": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"newLine": "lf",
"noEmit": true
},
"include": [
"**/*.ts",
"**/*.js"
],
"exclude": [
"node_modules/**"
]
}
================================================
FILE: .eslint-plugin-local/utils.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';
import { TSESTree } from '@typescript-eslint/utils';
export function createImportRuleListener(validateImport: (node: TSESTree.Literal, value: string) => any): eslint.Rule.RuleListener {
function _checkImport(node: TSESTree.Node | null) {
if (node && node.type === 'Literal' && typeof node.value === 'string') {
validateImport(node, node.value);
}
}
return {
// import ??? from 'module'
ImportDeclaration: (node: any) => {
_checkImport((node).source);
},
// import('module').then(...) OR await import('module')
['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node: any) => {
_checkImport(node);
},
// import foo = ...
['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node: any) => {
_checkImport(node);
},
// export ?? from 'module'
ExportAllDeclaration: (node: any) => {
_checkImport((node).source);
},
// export {foo} from 'module'
ExportNamedDeclaration: (node: any) => {
_checkImport((node).source);
},
};
}
================================================
FILE: .eslint-plugin-local/vscode-dts-cancellation.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';
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
noToken: 'Function lacks a cancellation token, preferable as last argument',
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature[key.name=/^(provide|resolve).+/]']: (node: any) => {
let found = false;
for (const param of (node).params) {
if (param.type === AST_NODE_TYPES.Identifier) {
found = found || param.name === 'token';
}
}
if (!found) {
context.report({
node,
messageId: 'noToken'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-create-func.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';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils';
export = 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' },
messages: { sync: '`createXYZ`-functions are constructor-replacements and therefore must return sync', },
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSDeclareFunction Identifier[name=/create.*/]']: (node: any) => {
const decl = (node).parent;
if (decl.returnType?.typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) {
return;
}
if (decl.returnType.typeAnnotation.typeName.type !== AST_NODE_TYPES.Identifier) {
return;
}
const ident = decl.returnType.typeAnnotation.typeName.name;
if (ident === 'Promise' || ident === 'Thenable') {
context.report({
node,
messageId: 'sync'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-event-naming.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';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils';
export = new class ApiEventNaming implements eslint.Rule.RuleModule {
private static _nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/;
readonly meta: eslint.Rule.RuleMetaData = {
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#event-naming'
},
messages: {
naming: 'Event names must follow this patten: `on[Did|Will]`',
verb: 'Unknown verb \'{{verb}}\' - is this really a verb? Iff so, then add this verb to the configuration',
subject: 'Unknown subject \'{{subject}}\' - This subject has not been used before but it should refer to something in the API',
unknown: 'UNKNOWN event declaration, lint-rule needs tweaking'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const config = <{ allowed: string[]; verbs: string[] }>context.options[0];
const allowed = new Set(config.allowed);
const verbs = new Set(config.verbs);
return {
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node: any) => {
const def = (node).parent?.parent?.parent;
const ident = this.getIdent(def);
if (!ident) {
// event on unknown structure...
return context.report({
node,
message: 'unknown'
});
}
if (allowed.has(ident.name)) {
// configured exception
return;
}
const match = ApiEventNaming._nameRegExp.exec(ident.name);
if (!match) {
context.report({
node: ident,
messageId: 'naming'
});
return;
}
// check that is spelled out (configured) as verb
if (!verbs.has(match[2].toLowerCase())) {
context.report({
node: ident,
messageId: 'verb',
data: { verb: match[2] }
});
}
// check that a subject (if present) has occurred
if (match[3]) {
const regex = new RegExp(match[3], 'ig');
const parts = context.getSourceCode().getText().split(regex);
if (parts.length < 3) {
context.report({
node: ident,
messageId: 'subject',
data: { subject: match[3] }
});
}
}
}
};
}
private getIdent(def: TSESTree.Node | undefined): TSESTree.Identifier | undefined {
if (!def) {
return;
}
if (def.type === AST_NODE_TYPES.Identifier) {
return def;
} else if ((def.type === AST_NODE_TYPES.TSPropertySignature || def.type === AST_NODE_TYPES.PropertyDefinition) && def.key.type === AST_NODE_TYPES.Identifier) {
return def.key;
}
return this.getIdent(def.parent);
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-interface-naming.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';
import { TSESTree } from '@typescript-eslint/utils';
export = new class ApiInterfaceNaming implements eslint.Rule.RuleModule {
private static _nameRegExp = /^I[A-Z]/;
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
naming: 'Interfaces must not be prefixed with uppercase `I`',
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSInterfaceDeclaration Identifier']: (node: any) => {
const name = (node).name;
if (ApiInterfaceNaming._nameRegExp.test(name)) {
context.report({
node,
messageId: 'naming'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-literal-or-types.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';
import { TSESTree } from '@typescript-eslint/utils';
export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' },
messages: { useEnum: 'Use enums, not literal-or-types', },
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSTypeAnnotation TSUnionType']: (node: any) => {
if ((node).types.every(value => value.type === 'TSLiteralType')) {
context.report({
node: node,
messageId: 'useEnum'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-provider-naming.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';
import { TSESTree } from '@typescript-eslint/utils';
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
naming: 'A provider should only have functions like provideXYZ or resolveXYZ',
},
schema: false,
};
private static _providerFunctionNames = /^(provide|resolve|prepare).+/;
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const config = <{ allowed: string[] }>context.options[0];
const allowed = new Set(config.allowed);
return {
['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node: any) => {
const interfaceName = ((node).parent?.parent).id.name;
if (allowed.has(interfaceName)) {
// allowed
return;
}
const methodName = ((node).key).name;
if (!ApiProviderNaming._providerFunctionNames.test(methodName)) {
context.report({
node,
messageId: 'naming'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-string-type-literals.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';
import { TSESTree } from '@typescript-eslint/utils';
export = new class ApiTypeDiscrimination implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines' },
messages: {
noTypeDiscrimination: 'Do not use type discrimination properties'
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSPropertySignature[optional=false] TSTypeAnnotation TSLiteralType Literal']: (node: any) => {
const raw = String((node).raw);
if (/^('|").*\1$/.test(raw)) {
context.report({
node: node,
messageId: 'noTypeDiscrimination'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-use-export.ts
================================================
/*---------------------------------------------------------------------------------------------
* 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';
export = new class VscodeDtsUseExport implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
useExport: `Public api types must use 'export'`,
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSModuleDeclaration :matches(TSInterfaceDeclaration, ClassDeclaration, VariableDeclaration, TSEnumDeclaration, TSTypeAliasDeclaration)']: (node: any) => {
const parent = (node).parent;
if (parent && parent.type !== TSESTree.AST_NODE_TYPES.ExportNamedDeclaration) {
context.report({
node,
messageId: 'useExport'
});
}
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-use-thenable.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 ApiEventNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
usage: 'Use the Thenable-type instead of the Promise type',
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSTypeAnnotation TSTypeReference Identifier[name="Promise"]']: (node: any) => {
context.report({
node,
messageId: 'usage',
});
}
};
}
};
================================================
FILE: .eslint-plugin-local/vscode-dts-vscode-in-comments.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';
import type * as estree from 'estree';
export = new class ApiVsCodeInComments implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
comment: `Don't use the term 'vs code' in comments`
},
schema: false,
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node: any) => {
for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Block') {
continue;
}
if (!comment.range) {
continue;
}
const startIndex = comment.range[0] + '/*'.length;
const re = /vs code/ig;
let match: RegExpExecArray | null;
while ((match = re.exec(comment.value))) {
// Allow using 'VS Code' in quotes
if (comment.value[match.index - 1] === `'` && comment.value[match.index + match[0].length] === `'`) {
continue;
}
// Types for eslint seem incorrect
const start = sourceCode.getLocFromIndex(startIndex + match.index) as any as estree.Position;
const end = sourceCode.getLocFromIndex(startIndex + match.index + match[0].length) as any as estree.Position;
context.report({
messageId: 'comment',
loc: { start, end }
});
}
}
}
};
}
};
================================================
FILE: .git-blame-ignore-revs
================================================
# https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt
# https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view
# mjbvz: Fix spacing
13f4f052582bcec3d6c6c6a70d995c9dee2cac13
# mjbvz: Add script to run build with noImplicitOverride
ae1452eea678f5266ef513f22dacebb90955d6c9
# alexdima: Revert "bump version"
537ba0ef1791c090bb18bc68d727816c0451c117
# alexdima: bump version
387a0dcb82df729e316ca2518a9ed81a75482b18
# joaomoreno: add ghooks dev dependency
0dfc06e0f9de5925de792cdf9f0e6597bb25908f
# joaomoreno: line endings
12ab70d329a13dd5b18d892cd40edd7138259bc3
# mjbvz: organize imports
494cbbd02d67e87727ec885f98d19551aa33aad1
a3cb14be7f2cceadb17adf843675b1a59537dbbd
ee1655a82ebdfd38bf8792088a6602c69f7bbd94
# jrieken: new eslint-rule
4a130c40ed876644ed8af2943809d08221375408
# bpasero: ESM migration
6b924c51528e663dda5091a1493229a361676aca
================================================
FILE: .gitattributes
================================================
* text=auto
LICENSE.txt eol=crlf
ThirdPartyNotices.txt eol=crlf
*.bat eol=crlf
*.cmd eol=crlf
*.ps1 eol=lf
*.sh eol=lf
*.rtf -text
**/*.json linguist-language=jsonc
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
================================================
FILE: .github/ISSUE_TEMPLATE/issue_template.md
================================================
---
name: Issue
about: Submit an Issue to Void
title: For VSCode-related issues (eg builds), please start the title with `[App]`. Otherwise, start it with `[Bug]` or `[Feature]`.
---
1. Press `Cmd+Shift+P` in Void, and type `Help: About`. Please paste the information here. Also let us know any other relevant details, like the model and provider you're using if applicable.
2. Describe the issue/feature here!
================================================
FILE: .github/scripts/issue_triage.py
================================================
#!/usr/bin/env python
from __future__ import annotations
import os, sys, json, datetime, pathlib, textwrap, requests
from openai import OpenAI
REPO = "voideditor/void"
CACHE_FILE = pathlib.Path(".github/triage_cache.json")
STAMP_FILE = pathlib.Path(".github/last_triage.txt")
THEMES_MD = textwrap.dedent("""\
1. 🔗 LLM Integration & Provider Support
2. 🖥 App Build & Platform Compatibility
3. 🎯 Prompt, Token, and Cost Management
4. 🧩 Editor UX & Interaction Design
5. 🤖 Agent & Automation Features
6. ⚙️ System Config & Environment Setup
7. 🗃 Meta: Feature Comparison, Structure, and Naming
""").strip()
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
headers = {"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"}
# ───────── helpers ────────────────────────────────────────────────────────
def utc_iso_now() -> str:
return datetime.datetime.utcnow().replace(microsecond=0, tzinfo=datetime.timezone.utc).isoformat()
def read_stamp() -> str:
return STAMP_FILE.read_text().strip() if STAMP_FILE.exists() else "1970-01-01T00:00:00Z"
def save_stamp():
STAMP_FILE.parent.mkdir(parents=True, exist_ok=True)
STAMP_FILE.write_text(utc_iso_now())
def load_cache() -> dict[int, str]:
return json.loads(CACHE_FILE.read_text()) if CACHE_FILE.exists() else {}
def save_cache(d: dict[int, str]):
CACHE_FILE.parent.mkdir(parents=True, exist_ok=True)
CACHE_FILE.write_text(json.dumps(d, indent=2))
def fetch_open_issues(since_iso: str | None = None) -> list[dict]:
issues, page = [], 1
while True:
url = (
f"https://api.github.com/repos/{REPO}/issues"
f"?state=open&per_page=100&page={page}"
+ (f"&since={since_iso}" if since_iso else "")
)
chunk = requests.get(url, headers=headers).json()
if not chunk or (isinstance(chunk, dict) and chunk.get("message")):
break
issues.extend(i for i in chunk if "pull_request" not in i)
page += 1
return issues
# ───────── main ───────────────────────────────────────────────────────────
last_stamp = read_stamp()
changed = fetch_open_issues(since_iso=last_stamp)
# Fallback if **nothing** changed AND we have *no* existing output
if not changed:
cache_exists = CACHE_FILE.exists()
wiki_exists = pathlib.Path("wiki/Issue-Categories.md").exists()
if not cache_exists or not wiki_exists:
# first run or someone wiped the wiki → build from scratch
print("⏩ First run or empty wiki — fetching ALL open issues.", file=sys.stderr)
changed = fetch_open_issues() # full list
else:
print(f"✅ No issues updated since {last_stamp}. Nothing to classify.", file=sys.stderr)
save_stamp()
sys.exit(0)
# ---------------------------------------------------------------- prompt
issue_lines = "\n".join(f"- {i['title']} ({i['html_url']})" for i in changed)
prompt = textwrap.dedent(f"""\
You are an AI assistant helping triage GitHub issues into exactly 7 predefined themes.
Each issue must go into exactly one of the themes below:
{THEMES_MD}
Format your output in Markdown like:
## 🎯 Prompt, Token, and Cost Management
- [#123](https://github.com/org/repo/issues/123) – Title here
Classify these issues:
{issue_lines}
""")
resp = client.chat.completions.create(
model="gpt-4.1",
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
)
md = resp.choices[0].message.content
# ---------------------------------------------------------------- parse GPT
new_map: dict[int, str] = {}
current = None
for ln in md.splitlines():
if ln.startswith("##"):
current = ln.lstrip("# ").strip()
elif ln.lstrip().startswith("- [#"):
try:
num = int(ln.split("[#")[1].split("]")[0])
new_map[num] = current
except Exception:
pass # ignore malformed lines
cache = load_cache()
cache.update(new_map)
save_cache(cache)
save_stamp()
# ---------------------------------------------------------------- rebuild wiki
order = [
"🔗 LLM Integration & Provider Support",
"🖥 App Build & Platform Compatibility",
"🎯 Prompt, Token, and Cost Management",
"🧩 Editor UX & Interaction Design",
"🤖 Agent & Automation Features",
"⚙️ System Config & Environment Setup",
"🗃 Meta: Feature Comparison, Structure, and Naming",
]
sections: dict[str, list[int]] = {t: [] for t in order}
# ── fetch ALL current open issues once (PRs filtered out) ────────────────
title_map: dict[int, tuple[str, str]] = {}
open_now: set[int] = set()
page = 1
while True:
batch = fetch_open_issues(since_iso=None) if page == 1 else []
if not batch:
break
for it in batch:
num = it["number"]
title_map[num] = (it["title"], it["html_url"])
open_now.add(num)
page += 1
# 🧹 drop any cached IDs that are no longer open issues (e.g., became a PR or were closed)
for stale in set(cache) - open_now:
del cache[stale]
save_cache(cache) # persist cleaned cache
# build sections from cleaned cache
for num, theme in cache.items():
if theme in sections: # extra safety
sections[theme].append(num)
# ---------------------------------------------------------------- print roadmap
for theme in order:
issues = sections[theme]
if issues:
print(f"## {theme}")
for n in sorted(issues):
title, url = title_map.get(n, ("(missing)", f"https://github.com/{REPO}/issues/{n}"))
print(f"- [#{n}]({url}) – {title}")
print()
================================================
FILE: .github/workflows/triage.yml
================================================
name: Issue Triage to Wiki
on:
workflow_dispatch:
schedule:
- cron: '0 */6 * * *' # every 6 hrs (UTC)
jobs:
roadmap:
runs-on: ubuntu-latest
steps:
# 1️⃣ Check out code (so the script and cache files are present)
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 1 # shallow clone
# 2️⃣ Set up Python
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
# 3️⃣ Install dependencies
- name: Install Python dependencies
run: |
pip install openai requests
# 4️⃣ Clone your fork’s Wiki
- name: Clone your fork's Wiki
run: |
git clone https://x-access-token:${{ secrets.WIKI_TOKEN }}@github.com/${{ github.repository }}.wiki.git wiki
# 5️⃣ (Optional) Show repo tree for debugging
- name: Show repo tree (debug)
run: |
echo "PWD: $(pwd)"
ls -al
ls -al .github/scripts || true
ls -al void/.github/scripts || true
# 6️⃣ Generate roadmap and push only if it changed
- name: Generate roadmap directly into wiki
run: |
python .github/scripts/issue_triage.py > wiki/_new.md
if ! cmp -s wiki/_new.md wiki/Issue-Categories.md ; then
mv wiki/_new.md wiki/Issue-Categories.md
cd wiki
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add Issue-Categories.md
git commit -m "Auto-update Issue-Categories.md from GPT triage"
git push
else
echo "No content change – skipping wiki update"
fi
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.WIKI_TOKEN }}
================================================
FILE: .gitignore
================================================
.DS_Store
.cache
npm-debug.log
Thumbs.db
node_modules/
.build/
.vscode/extensions/**/out/
extensions/**/dist/
/out*/
/extensions/**/out/
build/node_modules
coverage/
test_data/
test-results/
test-results.xml
vscode.lsif
vscode.db
/.profile-oss
/cli/target
/cli/openssl
product.overrides.json
*.snap.actual
.vscode-test
# Void added these:
.tmp/
.tmp2/
.tool-versions
src/vs/workbench/contrib/void/browser/react/out/**
src/vs/workbench/contrib/void/browser/react/src2/**
================================================
FILE: .idx/dev.nix
================================================
# Created for Void
# To learn more about how to use Nix to configure your environment
# see: https://developers.google.com/idx/guides/customize-idx-env
{pkgs}: {
# Which nixpkgs channel to use.
channel = "stable-23.11"; # or "unstable"
# Use https://search.nixos.org/packages to find packages
packages = [
pkgs.nodejs_20
pkgs.yarn
pkgs.nodePackages.pnpm
pkgs.bun
pkgs.gh
];
# Sets environment variables in the workspace
env = {};
idx = {
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
extensions = [
# "vscodevim.vim"
];
workspace = {
# Runs when a workspace is first created with this `dev.nix` file
onCreate = {
npm-install = "npm ci --no-audit --prefer-offline --no-progress --timing";
# Open editors for the following files by default, if they exist:
default.openFiles = [
# Cover all the variations of language, src-dir, router (app/pages)
"pages/index.tsx" "pages/index.jsx"
"src/pages/index.tsx" "src/pages/index.jsx"
"app/page.tsx" "app/page.jsx"
"src/app/page.tsx" "src/app/page.jsx"
];
};
# To run something each time the workspace is (re)started, use the `onStart` hook
};
# Enable previews and customize configuration
previews = {
enable = true;
previews = {
web = {
command = ["npm" "run" "dev" "--" "--port" "$PORT" "--hostname" "0.0.0.0"];
manager = "web";
};
};
};
};
}
================================================
FILE: .lsifrc.json
================================================
{
"project": "src/tsconfig.json",
"source": "./package.json",
"package": "package.json",
"out": "vscode.lsif"
}
================================================
FILE: .mailmap
================================================
Daniel Imms Daniel Imms
Raymond Zhao
Tyler Leonhardt Tyler Leonhardt
João Moreno João Moreno
================================================
FILE: .mention-bot
================================================
{
"maxReviewers": 2,
"requiredOrgs": ["Microsoft"],
"skipAlreadyAssignedPR": true,
"skipAlreadyMentionedPR": true,
"skipCollaboratorPR": true
}
================================================
FILE: .npmrc
================================================
disturl="https://electronjs.org/headers"
target="34.3.2"
ms_build_id="11161073"
runtime="electron"
build_from_source="true"
legacy-peer-deps="true"
timeout=180000
================================================
FILE: .nvmrc
================================================
20.18.2
================================================
FILE: .voidrules
================================================
This is a fork of the VSCode repo called Void.
Most code we care about lives in src/vs/workbench/contrib/void.
You may often need to explore the full repo to find relevant parts of code.
Look for services and built-in functions that you might need to use to solve the problem.
In typescript, do NOT cast to types if not neccessary. NEVER lazily cast to 'any'. Find the correct type to apply and use it.
Do not add or remove semicolons to any of my files. Just go with convention and make the least number of changes.
Never modify files outside src/vs/workbench/contrib/void without consulting with the user first.
All types that map from a value A to B should be called bOfA. For example, if you create a hashmap that goes from toolId to toolName, it should be called toolNameOfToolId, etc.
Do not run anything to validate your changes; tell the user what to do instead.
================================================
FILE: .vscode/cglicenses.schema.json
================================================
{
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"required": [
"name",
"prependLicenseText"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the dependency"
},
"fullLicenseText": {
"type": "array",
"description": "The complete license text of the dependency",
"items": {
"type": "string"
}
},
"prependLicenseText": {
"type": "array",
"description": "A piece of text to prepend to the auto-detected license text of the dependency",
"items": {
"type": "string"
}
}
}
},
{
"type": "object",
"required": [
"name",
"fullLicenseText"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the dependency"
},
"fullLicenseText": {
"type": "array",
"description": "The complete license text of the dependency",
"items": {
"type": "string"
}
},
"prependLicenseText": {
"type": "array",
"description": "A piece of text to prepend to the auto-detected license text of the dependency",
"items": {
"type": "string"
}
}
}
},
{
"type": "object",
"required": [
"name",
"fullLicenseTextUri"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the dependency"
},
"fullLicenseTextUri": {
"type": "string",
"description": "The URI to the license text of this repository",
"format": "uri"
},
"prependLicenseText": {
"type": "array",
"description": "A piece of text to prepend to the auto-detected license text of the dependency",
"items": {
"type": "string"
}
}
}
}
]
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-import-aid/.vscode/launch.json
================================================
{
"configurations": [
{
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--enable-proposed-api=ms-vscode.vscode-selfhost-import-aid"
],
"name": "Launch Extension",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"request": "launch",
"type": "extensionHost"
}
]
}
================================================
FILE: .vscode/extensions/vscode-selfhost-import-aid/.vscode/settings.json
================================================
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-import-aid/package.json
================================================
{
"name": "vscode-selfhost-import-aid",
"displayName": "VS Code Selfhost Import Aid",
"description": "Util to improve dealing with imports",
"engines": {
"vscode": "^1.88.0"
},
"version": "0.0.1",
"publisher": "ms-vscode",
"categories": [
"Other"
],
"activationEvents": [
"onLanguage:typescript"
],
"main": "./out/extension.js",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/vscode.git"
},
"license": "MIT",
"scripts": {
"compile": "gulp compile-extension:vscode-selfhost-import-aid",
"watch": "gulp watch-extension:vscode-selfhost-import-aid"
},
"dependencies": {
"typescript": "5.5.4"
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-import-aid/src/extension.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 vscode from 'vscode';
import * as ts from 'typescript';
import * as path from 'path';
export async function activate(context: vscode.ExtensionContext) {
const fileIndex = new class {
private _currentRun?: Thenable;
private _disposables: vscode.Disposable[] = [];
private readonly _index = new Map();
constructor() {
const watcher = vscode.workspace.createFileSystemWatcher('**/*.ts', false, true, false);
this._disposables.push(watcher.onDidChange(e => { this._index.set(e.toString(), e); }));
this._disposables.push(watcher.onDidDelete(e => { this._index.delete(e.toString()); }));
this._disposables.push(watcher);
this._refresh(false);
}
dispose(): void {
for (const disposable of this._disposables) {
disposable.dispose();
}
this._disposables = [];
this._index.clear();
}
async all(token: vscode.CancellationToken) {
await Promise.race([this._currentRun, new Promise(resolve => token.onCancellationRequested(resolve))]);
if (token.isCancellationRequested) {
return undefined;
}
return Array.from(this._index.values());
}
private _refresh(clear: boolean) {
// TODO@jrieken LATEST API! findFiles2New
this._currentRun = vscode.workspace.findFiles('src/vs/**/*.ts', '{**/node_modules/**,**/extensions/**}').then(all => {
if (clear) {
this._index.clear();
}
for (const item of all) {
this._index.set(item.toString(), item);
}
});
}
};
const selector: vscode.DocumentSelector = 'typescript';
function findNodeAtPosition(document: vscode.TextDocument, node: ts.Node, position: vscode.Position): ts.Node | undefined {
if (node.getStart() <= document.offsetAt(position) && node.getEnd() >= document.offsetAt(position)) {
return ts.forEachChild(node, child => findNodeAtPosition(document, child, position)) || node;
}
return undefined;
}
function findImportAt(document: vscode.TextDocument, position: vscode.Position): ts.ImportDeclaration | undefined {
const sourceFile = ts.createSourceFile(document.fileName, document.getText(), ts.ScriptTarget.Latest, true);
const node = findNodeAtPosition(document, sourceFile, position);
if (node && ts.isStringLiteral(node) && ts.isImportDeclaration(node.parent)) {
return node.parent;
}
return undefined;
}
const completionProvider = new class implements vscode.CompletionItemProvider {
async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise {
const index = document.getText().lastIndexOf(' from \'');
if (index < 0 || document.positionAt(index).line < position.line) {
// line after last import is before position
// -> no completion, safe a parse call
return undefined;
}
const node = findImportAt(document, position);
if (!node) {
return undefined;
}
const range = new vscode.Range(document.positionAt(node.moduleSpecifier.pos), document.positionAt(node.moduleSpecifier.end));
const uris = await fileIndex.all(token);
if (!uris) {
return undefined;
}
const result = new vscode.CompletionList();
result.isIncomplete = true;
for (const item of uris) {
if (!item.path.endsWith('.ts')) {
continue;
}
let relativePath = path.relative(path.dirname(document.uri.path), item.path);
relativePath = relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
const label = path.basename(item.path, path.extname(item.path));
const insertText = ` '${relativePath.replace(/\.ts$/, '.js')}'`;
const filterText = ` '${label}'`;
const completion = new vscode.CompletionItem({
label: label,
description: vscode.workspace.asRelativePath(item),
});
completion.kind = vscode.CompletionItemKind.File;
completion.insertText = insertText;
completion.filterText = filterText;
completion.range = range;
result.items.push(completion);
}
return result;
}
};
class ImportCodeActions implements vscode.CodeActionProvider {
static FixKind = vscode.CodeActionKind.QuickFix.append('esmImport');
static SourceKind = vscode.CodeActionKind.SourceFixAll.append('esmImport');
async provideCodeActions(document: vscode.TextDocument, range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise {
if (context.only && ImportCodeActions.SourceKind.intersects(context.only)) {
return this._provideFixAll(document, context, token);
}
return this._provideFix(document, range, context, token);
}
private async _provideFixAll(document: vscode.TextDocument, context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise {
const diagnostics = context.diagnostics
.filter(d => d.code === 2307)
.sort((a, b) => b.range.start.compareTo(a.range.start));
if (diagnostics.length === 0) {
return undefined;
}
const uris = await fileIndex.all(token);
if (!uris) {
return undefined;
}
const result = new vscode.CodeAction(`Fix All ESM Imports`, ImportCodeActions.SourceKind);
result.edit = new vscode.WorkspaceEdit();
result.diagnostics = [];
for (const diag of diagnostics) {
const actions = this._provideFixesForDiag(document, diag, uris);
if (actions.length === 0) {
console.log(`ESM: no fixes for "${diag.message}"`);
continue;
}
if (actions.length > 1) {
console.log(`ESM: more than one fix for "${diag.message}", taking first`);
console.log(actions);
}
const [first] = actions;
result.diagnostics.push(diag);
for (const [uri, edits] of first.edit!.entries()) {
result.edit.set(uri, edits);
}
}
// console.log(result.edit.get(document.uri));
return [result];
}
private async _provideFix(document: vscode.TextDocument, range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise {
const uris = await fileIndex.all(token);
if (!uris) {
return [];
}
const diag = context.diagnostics.find(d => d.code === 2307 && d.range.intersection(range));
return diag && this._provideFixesForDiag(document, diag, uris);
}
private _provideFixesForDiag(document: vscode.TextDocument, diag: vscode.Diagnostic, uris: Iterable): vscode.CodeAction[] {
const node = findImportAt(document, diag.range.start)?.moduleSpecifier;
if (!node || !ts.isStringLiteral(node)) {
return [];
}
const nodeRange = new vscode.Range(document.positionAt(node.pos), document.positionAt(node.end));
const name = path.basename(node.text, path.extname(node.text));
const result: vscode.CodeAction[] = [];
for (const item of uris) {
if (path.basename(item.path, path.extname(item.path)) === name) {
let relativePath = path.relative(path.dirname(document.uri.path), item.path).replace(/\.ts$/, '.js');
relativePath = relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
const action = new vscode.CodeAction(`Fix to '${relativePath}'`, ImportCodeActions.FixKind);
action.edit = new vscode.WorkspaceEdit();
action.edit.replace(document.uri, nodeRange, ` '${relativePath}'`);
action.diagnostics = [diag];
result.push(action);
}
}
return result;
}
}
context.subscriptions.push(fileIndex);
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(selector, completionProvider));
context.subscriptions.push(vscode.languages.registerCodeActionsProvider(selector, new ImportCodeActions(), { providedCodeActionKinds: [ImportCodeActions.FixKind, ImportCodeActions.SourceKind] }));
}
================================================
FILE: .vscode/extensions/vscode-selfhost-import-aid/tsconfig.json
================================================
{
"extends": "../../../extensions/tsconfig.base.json",
"compilerOptions": {
"outDir": "./out",
"types": [
"node",
"mocha",
]
},
"include": [
"src/**/*",
"../../../src/vscode-dts/vscode.d.ts"
]
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/.vscode/launch.json
================================================
{
"configurations": [
{
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--enable-proposed-api=ms-vscode.vscode-selfhost-test-provider"],
"name": "Launch Extension",
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"request": "launch",
"type": "extensionHost"
}
]
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/.vscode/settings.json
================================================
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/package.json
================================================
{
"name": "vscode-selfhost-test-provider",
"displayName": "VS Code Selfhost Test Provider",
"description": "Test provider for the VS Code project",
"enabledApiProposals": [
"testObserver",
"testRelatedCode"
],
"engines": {
"vscode": "^1.88.0"
},
"contributes": {
"commands": [
{
"command": "selfhost-test-provider.updateSnapshot",
"title": "Update Snapshot",
"category": "Testing",
"icon": "$(merge)"
},
{
"command": "selfhost-test-provider.openFailureLog",
"title": "Open Selfhost Failure Logs",
"category": "Testing",
"icon": "$(merge)"
}
],
"menus": {
"commandPalette": [
{
"command": "selfhost-test-provider.updateSnapshot",
"when": "false"
}
],
"testing/message/context": [
{
"command": "selfhost-test-provider.updateSnapshot",
"group": "inline@1",
"when": "testMessage == isSelfhostSnapshotMessage && !testResultOutdated"
}
],
"testing/message/content": [
{
"command": "selfhost-test-provider.updateSnapshot",
"when": "testMessage == isSelfhostSnapshotMessage && !testResultOutdated"
}
]
}
},
"icon": "icon.png",
"version": "0.4.0",
"publisher": "ms-vscode",
"categories": [
"Other"
],
"activationEvents": [
"workspaceContains:src/vs/loader.js"
],
"workspaceTrust": {
"request": "onDemand",
"description": "Trust is required to execute tests in the workspace."
},
"main": "./out/extension.js",
"prettier": {
"printWidth": 100,
"singleQuote": true,
"tabWidth": 2,
"arrowParens": "avoid"
},
"repository": {
"type": "git",
"url": "https://github.com/microsoft/vscode.git"
},
"license": "MIT",
"scripts": {
"compile": "gulp compile-extension:vscode-selfhost-test-provider",
"watch": "gulp watch-extension:vscode-selfhost-test-provider",
"test": "npx mocha --ui tdd 'out/*.test.js'"
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"@types/node": "20.x"
},
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
"ansi-styles": "^5.2.0",
"cockatiel": "^3.1.3",
"istanbul-to-vscode": "^2.0.1"
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/coverageProvider.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IstanbulCoverageContext } from 'istanbul-to-vscode';
import * as vscode from 'vscode';
import { SearchStrategy, SourceLocationMapper, SourceMapStore } from './testOutputScanner';
import { IScriptCoverage, OffsetToPosition, RangeCoverageTracker } from './v8CoverageWrangling';
export const istanbulCoverageContext = new IstanbulCoverageContext();
/**
* Tracks coverage in per-script coverage mode. There are two modes of coverage
* in this extension: generic istanbul reports, and reports from the runtime
* sent before and after each test case executes. This handles the latter.
*/
export class PerTestCoverageTracker {
private readonly scripts = new Map* script ID */ string, Script>();
constructor(private readonly maps: SourceMapStore) { }
public add(coverage: IScriptCoverage, test?: vscode.TestItem) {
const script = this.scripts.get(coverage.scriptId);
if (script) {
return script.add(coverage, test);
}
// ignore internals and node_modules
if (!coverage.url.startsWith('file://') || coverage.url.includes('node_modules')) {
return;
}
if (!coverage.source) {
throw new Error('expected to have source the first time a script is seen');
}
const src = new Script(vscode.Uri.parse(coverage.url), coverage.source, this.maps);
this.scripts.set(coverage.scriptId, src);
src.add(coverage, test);
}
public async report(run: vscode.TestRun) {
await Promise.all(Array.from(this.scripts.values()).map(s => s.report(run)));
}
}
class Script {
private converter: OffsetToPosition;
/** Tracking the overall coverage for the file */
private overall = new ScriptCoverageTracker();
/** Range tracking per-test item */
private readonly perItem = new Map();
constructor(
public readonly uri: vscode.Uri,
source: string,
private readonly maps: SourceMapStore
) {
this.converter = new OffsetToPosition(source);
}
public add(coverage: IScriptCoverage, test?: vscode.TestItem) {
this.overall.add(coverage);
if (test) {
const p = new ScriptCoverageTracker();
p.add(coverage);
this.perItem.set(test, p);
}
}
public async report(run: vscode.TestRun) {
const mapper = await this.maps.getSourceLocationMapper(this.uri.toString());
const originalUri = (await this.maps.getSourceFile(this.uri.toString())) || this.uri;
run.addCoverage(this.overall.report(originalUri, this.converter, mapper, this.perItem));
}
}
class ScriptCoverageTracker {
private coverage = new RangeCoverageTracker();
public add(coverage: IScriptCoverage) {
for (const range of RangeCoverageTracker.initializeBlocks(coverage.functions)) {
this.coverage.setCovered(range.start, range.end, range.covered);
}
}
public *toDetails(
uri: vscode.Uri,
convert: OffsetToPosition,
mapper: SourceLocationMapper | undefined,
) {
for (const range of this.coverage) {
if (range.start === range.end) {
continue;
}
const startCov = convert.toLineColumn(range.start);
let start = new vscode.Position(startCov.line, startCov.column);
const endCov = convert.toLineColumn(range.end);
let end = new vscode.Position(endCov.line, endCov.column);
if (mapper) {
const startMap = mapper(start.line, start.character, SearchStrategy.FirstAfter);
const endMap = startMap && mapper(end.line, end.character, SearchStrategy.FirstBefore);
if (!endMap || uri.toString().toLowerCase() !== endMap.uri.toString().toLowerCase()) {
continue;
}
start = startMap.range.start;
end = endMap.range.end;
}
for (let i = start.line; i <= end.line; i++) {
yield new vscode.StatementCoverage(
range.covered,
new vscode.Range(
new vscode.Position(i, i === start.line ? start.character : 0),
new vscode.Position(i, i === end.line ? end.character : Number.MAX_SAFE_INTEGER)
)
);
}
}
}
/**
* Generates the script's coverage for the test run.
*
* If a source location mapper is given, it assumes the `uri` is the mapped
* URI, and that any unmapped locations/outside the URI should be ignored.
*/
public report(
uri: vscode.Uri,
convert: OffsetToPosition,
mapper: SourceLocationMapper | undefined,
items: Map,
): V8CoverageFile {
const file = new V8CoverageFile(uri, items, convert, mapper);
for (const detail of this.toDetails(uri, convert, mapper)) {
file.add(detail);
}
return file;
}
}
export class V8CoverageFile extends vscode.FileCoverage {
public details: vscode.StatementCoverage[] = [];
constructor(
uri: vscode.Uri,
private readonly perTest: Map,
private readonly convert: OffsetToPosition,
private readonly mapper: SourceLocationMapper | undefined,
) {
super(uri, { covered: 0, total: 0 }, undefined, undefined, [...perTest.keys()]);
}
public add(detail: vscode.StatementCoverage) {
this.details.push(detail);
this.statementCoverage.total++;
if (detail.executed) {
this.statementCoverage.covered++;
}
}
public testDetails(test: vscode.TestItem): vscode.FileCoverageDetail[] {
const t = this.perTest.get(test);
return t ? [...t.toDetails(this.uri, this.convert, this.mapper)] : [];
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/debounce.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Debounces the function call for an interval.
*/
export function debounce(duration: number, fn: () => void): (() => void) & { clear: () => void } {
let timeout: NodeJS.Timeout | void;
const debounced = () => {
if (timeout !== undefined) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
timeout = undefined;
fn();
}, duration);
};
debounced.clear = () => {
if (timeout) {
clearTimeout(timeout);
timeout = undefined;
}
};
return debounced;
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/extension.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { randomBytes } from 'crypto';
import { tmpdir } from 'os';
import * as path from 'path';
import * as vscode from 'vscode';
import { V8CoverageFile } from './coverageProvider';
import { FailingDeepStrictEqualAssertFixer } from './failingDeepStrictEqualAssertFixer';
import { FailureTracker } from './failureTracker';
import { registerSnapshotUpdate } from './snapshot';
import { scanTestOutput } from './testOutputScanner';
import {
TestCase,
TestFile,
clearFileDiagnostics,
guessWorkspaceFolder,
itemData,
} from './testTree';
import { BrowserTestRunner, PlatformTestRunner, VSCodeTestRunner } from './vscodeTestRunner';
import { ImportGraph } from './importGraph';
const TEST_FILE_PATTERN = 'src/vs/**/*.{test,integrationTest}.ts';
const getWorkspaceFolderForTestFile = (uri: vscode.Uri) =>
(uri.path.endsWith('.test.ts') || uri.path.endsWith('.integrationTest.ts')) &&
uri.path.includes('/src/vs/')
? vscode.workspace.getWorkspaceFolder(uri)
: undefined;
const browserArgs: [name: string, arg: string][] = [
['Chrome', 'chromium'],
['Firefox', 'firefox'],
['Webkit', 'webkit'],
];
type FileChangeEvent = { uri: vscode.Uri; removed: boolean };
export async function activate(context: vscode.ExtensionContext) {
const ctrl = vscode.tests.createTestController('selfhost-test-controller', 'VS Code Tests');
const fileChangedEmitter = new vscode.EventEmitter();
context.subscriptions.push(vscode.tests.registerTestFollowupProvider({
async provideFollowup(_result, test, taskIndex, messageIndex, _token) {
return [{
title: '$(sparkle) Fix with Copilot',
command: 'github.copilot.tests.fixTestFailure',
arguments: [{ source: 'peekFollowup', test, message: test.taskStates[taskIndex].messages[messageIndex] }]
}];
},
}));
let initialWatchPromise: Promise | undefined;
const resolveHandler = async (test?: vscode.TestItem) => {
if (!test) {
if (!initialWatchPromise) {
initialWatchPromise = startWatchingWorkspace(ctrl, fileChangedEmitter);
context.subscriptions.push(await initialWatchPromise);
} else {
await initialWatchPromise;
}
return;
}
const data = itemData.get(test);
if (data instanceof TestFile) {
// No need to watch this, updates will be triggered on file changes
// either by the text document or file watcher.
await data.updateFromDisk(ctrl, test);
}
};
ctrl.resolveHandler = resolveHandler;
guessWorkspaceFolder().then(folder => {
if (!folder) {
return;
}
const graph = new ImportGraph(
folder.uri, async () => {
await resolveHandler();
return [...ctrl.items].map(([, item]) => item);
}, uri => ctrl.items.get(uri.toString().toLowerCase()));
ctrl.relatedCodeProvider = graph;
if (context.storageUri) {
context.subscriptions.push(new FailureTracker(context.storageUri.fsPath, folder.uri.fsPath));
}
context.subscriptions.push(fileChangedEmitter.event(e => graph.didChange(e.uri, e.removed)));
});
const createRunHandler = (
runnerCtor: { new(folder: vscode.WorkspaceFolder): VSCodeTestRunner },
kind: vscode.TestRunProfileKind,
args: string[] = []
) => {
const doTestRun = async (
req: vscode.TestRunRequest,
cancellationToken: vscode.CancellationToken
) => {
const folder = await guessWorkspaceFolder();
if (!folder) {
return;
}
const runner = new runnerCtor(folder);
const map = await getPendingTestMap(ctrl, req.include ?? gatherTestItems(ctrl.items));
const task = ctrl.createTestRun(req);
for (const test of map.values()) {
task.enqueued(test);
}
let coverageDir: string | undefined;
let currentArgs = args;
if (kind === vscode.TestRunProfileKind.Coverage) {
// todo: browser runs currently don't support per-test coverage
if (args.includes('--browser')) {
coverageDir = path.join(
tmpdir(),
`vscode-test-coverage-${randomBytes(8).toString('hex')}`
);
currentArgs = [
...currentArgs,
'--coverage',
'--coveragePath',
coverageDir,
'--coverageFormats',
'json',
];
} else {
currentArgs = [...currentArgs, '--per-test-coverage'];
}
}
return await scanTestOutput(
map,
task,
kind === vscode.TestRunProfileKind.Debug
? await runner.debug(task, currentArgs, req.include)
: await runner.run(currentArgs, req.include),
coverageDir,
cancellationToken
);
};
return async (req: vscode.TestRunRequest, cancellationToken: vscode.CancellationToken) => {
if (!req.continuous) {
return doTestRun(req, cancellationToken);
}
const queuedFiles = new Set();
let debounced: NodeJS.Timeout | undefined;
const listener = fileChangedEmitter.event(({ uri, removed }) => {
clearTimeout(debounced);
if (req.include && !req.include.some(i => i.uri?.toString() === uri.toString())) {
return;
}
if (removed) {
queuedFiles.delete(uri.toString());
} else {
queuedFiles.add(uri.toString());
}
debounced = setTimeout(() => {
const include =
req.include?.filter(t => t.uri && queuedFiles.has(t.uri?.toString())) ??
[...queuedFiles]
.map(f => getOrCreateFile(ctrl, vscode.Uri.parse(f)))
.filter((f): f is vscode.TestItem => !!f);
queuedFiles.clear();
doTestRun(
new vscode.TestRunRequest(include, req.exclude, req.profile, true),
cancellationToken
);
}, 1000);
});
cancellationToken.onCancellationRequested(() => {
clearTimeout(debounced);
listener.dispose();
});
};
};
ctrl.createRunProfile(
'Run in Electron',
vscode.TestRunProfileKind.Run,
createRunHandler(PlatformTestRunner, vscode.TestRunProfileKind.Run),
true,
undefined,
true
);
ctrl.createRunProfile(
'Debug in Electron',
vscode.TestRunProfileKind.Debug,
createRunHandler(PlatformTestRunner, vscode.TestRunProfileKind.Debug),
true,
undefined,
true
);
const coverage = ctrl.createRunProfile(
'Coverage in Electron',
vscode.TestRunProfileKind.Coverage,
createRunHandler(PlatformTestRunner, vscode.TestRunProfileKind.Coverage),
true,
undefined,
true
);
coverage.loadDetailedCoverage = async (_run, coverage) => coverage instanceof V8CoverageFile ? coverage.details : [];
coverage.loadDetailedCoverageForTest = async (_run, coverage, test) => coverage instanceof V8CoverageFile ? coverage.testDetails(test) : [];
for (const [name, arg] of browserArgs) {
const cfg = ctrl.createRunProfile(
`Run in ${name}`,
vscode.TestRunProfileKind.Run,
createRunHandler(BrowserTestRunner, vscode.TestRunProfileKind.Run, [' --browser', arg]),
undefined,
undefined,
true
);
cfg.configureHandler = () => vscode.window.showInformationMessage(`Configuring ${name}`);
ctrl.createRunProfile(
`Debug in ${name}`,
vscode.TestRunProfileKind.Debug,
createRunHandler(BrowserTestRunner, vscode.TestRunProfileKind.Debug, [
'--browser',
arg,
'--debug-browser',
]),
undefined,
undefined,
true
);
}
function updateNodeForDocument(e: vscode.TextDocument) {
const node = getOrCreateFile(ctrl, e.uri);
const data = node && itemData.get(node);
if (data instanceof TestFile) {
data.updateFromContents(ctrl, e.getText(), node!);
}
}
for (const document of vscode.workspace.textDocuments) {
updateNodeForDocument(document);
}
context.subscriptions.push(
ctrl,
fileChangedEmitter.event(({ uri, removed }) => {
if (!removed) {
const node = getOrCreateFile(ctrl, uri);
if (node) {
ctrl.invalidateTestResults();
}
}
}),
vscode.workspace.onDidOpenTextDocument(updateNodeForDocument),
vscode.workspace.onDidChangeTextDocument(e => updateNodeForDocument(e.document)),
registerSnapshotUpdate(ctrl),
new FailingDeepStrictEqualAssertFixer()
);
}
export function deactivate() {
// no-op
}
function getOrCreateFile(
controller: vscode.TestController,
uri: vscode.Uri
): vscode.TestItem | undefined {
const folder = getWorkspaceFolderForTestFile(uri);
if (!folder) {
return undefined;
}
const data = new TestFile(uri, folder);
const existing = controller.items.get(data.getId());
if (existing) {
return existing;
}
const file = controller.createTestItem(data.getId(), data.getLabel(), uri);
controller.items.add(file);
file.canResolveChildren = true;
itemData.set(file, data);
return file;
}
function gatherTestItems(collection: vscode.TestItemCollection) {
const items: vscode.TestItem[] = [];
collection.forEach(item => items.push(item));
return items;
}
async function startWatchingWorkspace(
controller: vscode.TestController,
fileChangedEmitter: vscode.EventEmitter
) {
const workspaceFolder = await guessWorkspaceFolder();
if (!workspaceFolder) {
return new vscode.Disposable(() => undefined);
}
const pattern = new vscode.RelativePattern(workspaceFolder, TEST_FILE_PATTERN);
const watcher = vscode.workspace.createFileSystemWatcher(pattern);
watcher.onDidCreate(uri => {
getOrCreateFile(controller, uri);
fileChangedEmitter.fire({ removed: false, uri });
});
watcher.onDidChange(uri => fileChangedEmitter.fire({ removed: false, uri }));
watcher.onDidDelete(uri => {
fileChangedEmitter.fire({ removed: true, uri });
clearFileDiagnostics(uri);
controller.items.delete(uri.toString());
});
for (const file of await vscode.workspace.findFiles(pattern)) {
getOrCreateFile(controller, file);
}
return watcher;
}
async function getPendingTestMap(ctrl: vscode.TestController, tests: Iterable) {
const queue = [tests];
const titleMap = new Map();
while (queue.length) {
for (const item of queue.pop()!) {
const data = itemData.get(item);
if (data instanceof TestFile) {
if (!data.hasBeenRead) {
await data.updateFromDisk(ctrl, item);
}
queue.push(gatherTestItems(item.children));
} else if (data instanceof TestCase) {
titleMap.set(data.fullName, item);
} else {
queue.push(gatherTestItems(item.children));
}
}
}
return titleMap;
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/failingDeepStrictEqualAssertFixer.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 ts from 'typescript';
import {
commands,
Disposable,
languages,
Position,
Range,
TestMessage,
TestResultSnapshot,
TestRunResult,
tests,
TextDocument,
Uri,
workspace,
WorkspaceEdit,
} from 'vscode';
import { memoizeLast } from './memoize';
import { getTestMessageMetadata } from './metadata';
const enum Constants {
FixCommandId = 'selfhost-test.fix-test',
}
export class FailingDeepStrictEqualAssertFixer {
private disposables: Disposable[] = [];
constructor() {
this.disposables.push(
commands.registerCommand(Constants.FixCommandId, async (uri: Uri, position: Position) => {
const document = await workspace.openTextDocument(uri);
const failingAssertion = detectFailingDeepStrictEqualAssertion(document, position);
if (!failingAssertion) {
return;
}
const expectedValueNode = failingAssertion.assertion.expectedValue;
if (!expectedValueNode) {
return;
}
const start = document.positionAt(expectedValueNode.getStart());
const end = document.positionAt(expectedValueNode.getEnd());
const edit = new WorkspaceEdit();
edit.replace(uri, new Range(start, end), formatJsonValue(failingAssertion.actualJSONValue));
await workspace.applyEdit(edit);
})
);
this.disposables.push(
languages.registerCodeActionsProvider('typescript', {
provideCodeActions: (document, range) => {
const failingAssertion = detectFailingDeepStrictEqualAssertion(document, range.start);
if (!failingAssertion) {
return undefined;
}
return [
{
title: 'Fix Expected Value',
command: Constants.FixCommandId,
arguments: [document.uri, range.start],
},
];
},
})
);
}
dispose() {
for (const d of this.disposables) {
d.dispose();
}
}
}
const identifierLikeRe = /^[$a-z_][a-z0-9_$]*$/i;
const tsPrinter = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const formatJsonValue = (value: unknown) => {
if (typeof value !== 'object') {
return JSON.stringify(value);
}
const src = ts.createSourceFile('', `(${JSON.stringify(value)})`, ts.ScriptTarget.ES5, true);
const outerExpression = src.statements[0] as ts.ExpressionStatement;
const parenExpression = outerExpression.expression as ts.ParenthesizedExpression;
const unquoted = ts.transform(parenExpression, [
context => (node: ts.Node) => {
const visitor = (node: ts.Node): ts.Node =>
ts.isPropertyAssignment(node) &&
ts.isStringLiteralLike(node.name) &&
identifierLikeRe.test(node.name.text)
? ts.factory.createPropertyAssignment(
ts.factory.createIdentifier(node.name.text),
ts.visitNode(node.initializer, visitor) as ts.Expression
)
: ts.isStringLiteralLike(node) && node.text === '[undefined]'
? ts.factory.createIdentifier('undefined')
: ts.visitEachChild(node, visitor, context);
return ts.visitNode(node, visitor);
},
]);
return tsPrinter.printNode(ts.EmitHint.Expression, unquoted.transformed[0], src);
};
/** Parses the source file, memoizing the last document so cursor moves are efficient */
const parseSourceFile = memoizeLast((text: string) =>
ts.createSourceFile('', text, ts.ScriptTarget.ES5, true)
);
const assertionFailureMessageRe = /^Expected values to be strictly (deep-)?equal:/;
/** Gets information about the failing assertion at the poisition, if any. */
function detectFailingDeepStrictEqualAssertion(
document: TextDocument,
position: Position
): { assertion: StrictEqualAssertion; actualJSONValue: unknown } | undefined {
const sf = parseSourceFile(document.getText());
const offset = document.offsetAt(position);
const assertion = StrictEqualAssertion.atPosition(sf, offset);
if (!assertion) {
return undefined;
}
const startLine = document.positionAt(assertion.offsetStart).line;
const messages = getAllTestStatusMessagesAt(document.uri, startLine);
const strictDeepEqualMessage = messages.find(m =>
assertionFailureMessageRe.test(typeof m.message === 'string' ? m.message : m.message.value)
);
if (!strictDeepEqualMessage) {
return undefined;
}
const metadata = getTestMessageMetadata(strictDeepEqualMessage);
if (!metadata) {
return undefined;
}
return {
assertion: assertion,
actualJSONValue: metadata.actualValue,
};
}
class StrictEqualAssertion {
/**
* Extracts the assertion at the current node, if it is one.
*/
public static fromNode(node: ts.Node): StrictEqualAssertion | undefined {
if (!ts.isCallExpression(node)) {
return undefined;
}
const expr = node.expression.getText();
if (expr !== 'assert.deepStrictEqual' && expr !== 'assert.strictEqual') {
return undefined;
}
return new StrictEqualAssertion(node);
}
/**
* Gets the equals assertion at the given offset in the file.
*/
public static atPosition(sf: ts.SourceFile, offset: number): StrictEqualAssertion | undefined {
let node = findNodeAt(sf, offset);
while (node.parent) {
const obj = StrictEqualAssertion.fromNode(node);
if (obj) {
return obj;
}
node = node.parent;
}
return undefined;
}
constructor(private readonly expression: ts.CallExpression) { }
/** Gets the expected value */
public get expectedValue(): ts.Expression | undefined {
return this.expression.arguments[1];
}
/** Gets the position of the assertion expression. */
public get offsetStart(): number {
return this.expression.getStart();
}
}
function findNodeAt(parent: ts.Node, offset: number): ts.Node {
for (const child of parent.getChildren()) {
if (child.getStart() <= offset && offset <= child.getEnd()) {
return findNodeAt(child, offset);
}
}
return parent;
}
function getAllTestStatusMessagesAt(uri: Uri, lineNumber: number): TestMessage[] {
if (tests.testResults.length === 0) {
return [];
}
const run = tests.testResults[0];
const snapshots = getTestResultsWithUri(run, uri);
const result: TestMessage[] = [];
for (const snapshot of snapshots) {
for (const m of snapshot.taskStates[0].messages) {
if (
m.location &&
m.location.range.start.line <= lineNumber &&
lineNumber <= m.location.range.end.line
) {
result.push(m);
}
}
}
return result;
}
function getTestResultsWithUri(testRun: TestRunResult, uri: Uri): TestResultSnapshot[] {
const results: TestResultSnapshot[] = [];
const walk = (r: TestResultSnapshot) => {
for (const c of r.children) {
walk(c);
}
if (r.uri?.toString() === uri.toString()) {
results.push(r);
}
};
for (const r of testRun.results) {
walk(r);
}
return results;
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/failureTracker.ts
================================================
/*---------------------------------------------------------------------------------------------
* 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 { existsSync, mkdirSync, renameSync } from 'fs';
import { readFile, writeFile } from 'fs/promises';
import { dirname, join } from 'path';
import * as vscode from 'vscode';
interface IGitState {
commitId: string;
tracked: string;
untracked: Record;
}
interface ITrackedRemediation {
snapshot: vscode.TestResultSnapshot;
failing: IGitState;
passing: IGitState;
}
const MAX_FAILURES = 10;
export class FailureTracker {
private readonly disposables: vscode.Disposable[] = [];
private readonly lastFailed = new Map<
string,
{ snapshot: vscode.TestResultSnapshot; failing: IGitState }
>();
private readonly logFile: string;
private logs?: ITrackedRemediation[];
constructor(storageLocation: string, private readonly rootDir: string) {
this.logFile = join(storageLocation, '.build/vscode-test-failures.json');
mkdirSync(dirname(this.logFile), { recursive: true });
const oldLogFile = join(rootDir, '.build/vscode-test-failures.json');
if (existsSync(oldLogFile)) {
try {
renameSync(oldLogFile, this.logFile);
} catch {
// ignore
}
}
this.disposables.push(
vscode.commands.registerCommand('selfhost-test-provider.openFailureLog', async () => {
const doc = await vscode.workspace.openTextDocument(this.logFile);
await vscode.window.showTextDocument(doc);
})
);
this.disposables.push(
vscode.tests.onDidChangeTestResults(() => {
const last = vscode.tests.testResults[0];
if (!last) {
return;
}
let gitState: Promise | undefined;
const getGitState = () => gitState ?? (gitState = this.captureGitState());
const queue = [last.results];
for (let i = 0; i < queue.length; i++) {
for (const snapshot of queue[i]) {
// only interested in states of leaf tests
if (snapshot.children.length) {
queue.push(snapshot.children);
continue;
}
const key = `${snapshot.uri}/${snapshot.id}`;
const prev = this.lastFailed.get(key);
if (snapshot.taskStates.some(s => s.state === vscode.TestResultState.Failed)) {
// unset the parent to avoid a circular JSON structure:
getGitState().then(s =>
this.lastFailed.set(key, {
snapshot: { ...snapshot, parent: undefined },
failing: s,
})
);
} else if (prev) {
this.lastFailed.delete(key);
getGitState().then(s => this.append({ ...prev, passing: s }));
}
}
}
})
);
}
private async append(log: ITrackedRemediation) {
if (!this.logs) {
try {
this.logs = JSON.parse(await readFile(this.logFile, 'utf-8'));
} catch {
this.logs = [];
}
}
const logs = this.logs!;
logs.push(log);
if (logs.length > MAX_FAILURES) {
logs.splice(0, logs.length - MAX_FAILURES);
}
await writeFile(this.logFile, JSON.stringify(logs, undefined, 2));
}
private async captureGitState() {
const [commitId, tracked, untracked] = await Promise.all([
this.exec('git', ['rev-parse', 'HEAD']),
this.exec('git', ['diff', 'HEAD']),
this.exec('git', ['ls-files', '--others', '--exclude-standard']).then(async output => {
const mapping: Record = {};
await Promise.all(
output
.trim()
.split('\n')
.map(async f => {
mapping[f] = await readFile(join(this.rootDir, f), 'utf-8');
})
);
return mapping;
}),
]);
return { commitId, tracked, untracked };
}
public dispose() {
this.disposables.forEach(d => d.dispose());
}
private exec(command: string, args: string[]): Promise {
return new Promise((resolve, reject) => {
const child = spawn(command, args, { stdio: 'pipe', cwd: this.rootDir });
let output = '';
child.stdout.setEncoding('utf-8').on('data', b => (output += b));
child.stderr.setEncoding('utf-8').on('data', b => (output += b));
child.on('error', reject);
child.on('exit', code =>
code === 0
? resolve(output)
: reject(new Error(`Failed with error code ${code}\n${output}`))
);
});
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/importGraph.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { join } from 'path';
import * as vscode from 'vscode';
import { bulkhead } from 'cockatiel';
import { promises as fs } from 'fs';
const maxInt32 = 2 ** 31 - 1;
// limit concurrency to avoid overwhelming the filesystem during discovery
const discoverLimiter = bulkhead(8, Infinity);
// Max import distance when listing related code to improve relevancy.
const defaultMaxDistance = 3;
/**
* Maintains a graph of imports in the codebase. This works lazily resolving
* imports and re-parsing files only on request.
*
* This is a rough, file-level graph derived from simple regex matching on
* source files to avoid having to parse the AST of every file in the codebase,
* which is possible but more intensive. (See: all the years of work from the
* TS language server.)
*
* A more advanced implementation could use references from the language server.
*/
export class ImportGraph implements vscode.TestRelatedCodeProvider {
private graph = new Map();
constructor(
private readonly root: vscode.Uri,
private readonly discoverWorkspaceTests: () => Thenable,
private readonly getTestNodeForDoc: (uri: vscode.Uri) => vscode.TestItem | undefined,
) { }
/** @inheritdoc */
public async provideRelatedCode(test: vscode.TestItem, token: vscode.CancellationToken): Promise {
// this is kind of a stub for this implementation. Naive following imports
// isn't that useful for finding a test's related code.
const node = await this.discoverOutwards(test.uri, new Set(), defaultMaxDistance, token);
if (!node) {
return [];
}
const imports = new Set();
const queue = [{ distance: 0, next: node.imports }];
while (queue.length) {
const { distance, next } = queue.shift()!;
for (const imp of next) {
if (imports.has(imp.path)) {
continue;
}
imports.add(imp.path);
if (distance < defaultMaxDistance) {
queue.push({ next: imp.imports, distance: distance + 1 });
}
}
}
return [...imports].map(importPath =>
new vscode.Location(
vscode.Uri.file(join(this.root.fsPath, 'src', `${importPath}.ts`)),
new vscode.Range(0, 0, maxInt32, 0),
),
);
}
/** @inheritdoc */
public async provideRelatedTests(document: vscode.TextDocument, _position: vscode.Position, token: vscode.CancellationToken): Promise {
// Expand all known tests to ensure imports of this file are realized.
const rootTests = await this.discoverWorkspaceTests();
const seen = new Set();
await Promise.all(rootTests.map(v => v.uri && this.discoverOutwards(v.uri, seen, defaultMaxDistance, token)));
const node = this.getNode(document.uri);
if (!node) {
return [];
}
const tests: vscode.TestItem[] = [];
const queue: { next: FileNode; distance: number }[] = [{ next: node, distance: 0 }];
const visited = new Set();
let maxDistance = Infinity;
while (queue.length) {
const { next, distance } = queue.shift()!;
if (visited.has(next)) {
continue;
}
visited.add(next);
const testForDoc = this.getTestNodeForDoc(next.uri);
if (testForDoc) {
tests.push(testForDoc);
// only look for tests half again as far away as the closest test to keep things relevant
if (!Number.isFinite(maxDistance)) {
maxDistance = distance * 3 / 2;
}
}
if (distance < maxDistance) {
for (const importedByNode of next.importedBy) {
queue.push({ next: importedByNode, distance: distance + 1 });
}
}
}
return tests;
}
public didChange(uri: vscode.Uri, deleted: boolean) {
const rel = this.uriToImportPath(uri);
const node = rel && this.graph.get(rel);
if (!node) {
return;
}
if (deleted) {
this.graph.delete(rel);
for (const imp of node.imports) {
imp.importedBy.delete(node);
}
} else {
node.isSynced = false;
}
}
private getNode(uri: vscode.Uri | undefined): FileNode | undefined {
const rel = this.uriToImportPath(uri);
return rel ? this.graph.get(rel) : undefined;
}
/** Discover all nodes that import the file */
private async discoverOutwards(uri: vscode.Uri | undefined, seen: Set, maxDistance: number, token: vscode.CancellationToken): Promise {
const rel = this.uriToImportPath(uri);
if (!rel) {
return undefined;
}
let node = this.graph.get(rel);
if (!node) {
node = new FileNode(uri!, rel);
this.graph.set(rel, node);
}
await this.discoverOutwardsInner(node, seen, maxDistance, token);
return node;
}
private async discoverOutwardsInner(node: FileNode, seen: Set, maxDistance: number, token: vscode.CancellationToken) {
if (seen.has(node.path) || maxDistance === 0) {
return;
}
seen.add(node.path);
if (node.isSynced === false) {
await this.syncNode(node);
} else if (node.isSynced instanceof Promise) {
await node.isSynced;
}
if (token.isCancellationRequested) {
return;
}
await Promise.all([...node.imports].map(i => this.discoverOutwardsInner(i, seen, maxDistance - 1, token)));
}
private async syncNode(node: FileNode) {
node.isSynced = discoverLimiter.execute(async () => {
const doc = vscode.workspace.textDocuments.find(d => d.uri.toString() === node.uri.toString());
let text: string;
if (doc) {
text = doc.getText();
} else {
try {
text = await fs.readFile(node.uri.fsPath, 'utf8');
} catch {
text = '';
}
}
for (const imp of node.imports) {
imp.importedBy.delete(node);
}
node.imports.clear();
for (const [, importPath] of text.matchAll(IMPORT_RE)) {
let imp = this.graph.get(importPath);
if (!imp) {
imp = new FileNode(this.importPathToUri(importPath), importPath);
this.graph.set(importPath, imp);
}
imp.importedBy.add(node);
node.imports.add(imp);
}
node.isSynced = true;
});
await node.isSynced;
}
private uriToImportPath(uri: vscode.Uri | undefined) {
if (!uri) {
return undefined;
}
const relativePath = vscode.workspace.asRelativePath(uri).replaceAll('\\', '/');
if (!relativePath.startsWith('src/vs/') || !relativePath.endsWith('.ts')) {
return undefined;
}
return relativePath.slice('src/'.length, -'.ts'.length);
}
private importPathToUri(importPath: string) {
return vscode.Uri.file(join(this.root.fsPath, 'src', `${importPath}.ts`));
}
}
const IMPORT_RE = /import .*? from ["'](vs\/[^"']+)/g;
class FileNode {
public imports = new Set();
public importedBy = new Set();
public isSynced: boolean | Promise = false;
// Path is the *import path* starting with `vs/`
constructor(
public readonly uri: vscode.Uri,
public readonly path: string,
) { }
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/memoize.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const memoizeLast = (fn: (args: A) => T): ((args: A) => T) => {
let last: { arg: A; result: T } | undefined;
return arg => {
if (last && last.arg === arg) {
return last.result;
}
const result = fn(arg);
last = { arg, result };
return result;
};
};
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/metadata.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TestMessage } from 'vscode';
export interface TestMessageMetadata {
expectedValue: unknown;
actualValue: unknown;
}
const cache = new Array<{ id: string; metadata: TestMessageMetadata }>();
let id = 0;
function getId(): string {
return `msg:${id++}:`;
}
const regexp = /msg:\d+:/;
export function attachTestMessageMetadata(
message: TestMessage,
metadata: TestMessageMetadata
): void {
const existingMetadata = getTestMessageMetadata(message);
if (existingMetadata) {
Object.assign(existingMetadata, metadata);
return;
}
const id = getId();
if (typeof message.message === 'string') {
message.message = `${message.message}\n${id}`;
} else {
message.message.appendText(`\n${id}`);
}
cache.push({ id, metadata });
while (cache.length > 100) {
cache.shift();
}
}
export function getTestMessageMetadata(message: TestMessage): TestMessageMetadata | undefined {
let value: string;
if (typeof message.message === 'string') {
value = message.message;
} else {
value = message.message.value;
}
const result = regexp.exec(value);
if (!result) {
return undefined;
}
const id = result[0];
return cache.find(c => c.id === id)?.metadata;
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/snapshot.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { promises as fs } from 'fs';
import * as vscode from 'vscode';
export const snapshotComment = '\n\n// Snapshot file: ';
export const registerSnapshotUpdate = (ctrl: vscode.TestController) =>
vscode.commands.registerCommand('selfhost-test-provider.updateSnapshot', async args => {
const message: vscode.TestMessage = args.message;
const index = message.expectedOutput?.indexOf(snapshotComment);
if (!message.expectedOutput || !message.actualOutput || !index || index === -1) {
vscode.window.showErrorMessage('Could not find snapshot comment in message');
return;
}
const file = message.expectedOutput.slice(index + snapshotComment.length);
await fs.writeFile(file, message.actualOutput);
ctrl.invalidateTestResults(args.test);
});
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/sourceUtils.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 ts from 'typescript';
import * as vscode from 'vscode';
import { TestCase, TestConstruct, TestSuite, VSCodeTest } from './testTree';
const suiteNames = new Set(['suite', 'flakySuite']);
const testNames = new Set(['test']);
export const enum Action {
Skip,
Recurse,
}
export const extractTestFromNode = (src: ts.SourceFile, node: ts.Node, parent: VSCodeTest) => {
if (!ts.isCallExpression(node)) {
return Action.Recurse;
}
const asSuite = identifyCall(node.expression, suiteNames);
const asTest = identifyCall(node.expression, testNames);
const either = asSuite || asTest;
if (either === IdentifiedCall.Skipped) {
return Action.Skip;
}
if (either === IdentifiedCall.Nothing) {
return Action.Recurse;
}
const name = node.arguments[0];
const func = node.arguments[1];
if (!name || !ts.isStringLiteralLike(name) || !func) {
return Action.Recurse;
}
const start = src.getLineAndCharacterOfPosition(name.pos);
const end = src.getLineAndCharacterOfPosition(func.end);
const range = new vscode.Range(
new vscode.Position(start.line, start.character),
new vscode.Position(end.line, end.character)
);
const cparent = parent instanceof TestConstruct ? parent : undefined;
// we know this is either a suite or a test because we checked for skipped/nothing above
if (asTest) {
return new TestCase(name.text, range, cparent);
}
if (asSuite) {
return new TestSuite(name.text, range, cparent);
}
throw new Error('unreachable');
};
const enum IdentifiedCall {
Nothing,
Skipped,
IsThing,
}
const identifyCall = (lhs: ts.Node, needles: ReadonlySet): IdentifiedCall => {
if (ts.isIdentifier(lhs)) {
return needles.has(lhs.escapedText || lhs.text) ? IdentifiedCall.IsThing : IdentifiedCall.Nothing;
}
if (isPropertyCall(lhs) && lhs.name.text === 'skip') {
return needles.has(lhs.expression.text) ? IdentifiedCall.Skipped : IdentifiedCall.Nothing;
}
if (ts.isParenthesizedExpression(lhs) && ts.isConditionalExpression(lhs.expression)) {
return Math.max(identifyCall(lhs.expression.whenTrue, needles), identifyCall(lhs.expression.whenFalse, needles));
}
return IdentifiedCall.Nothing;
};
const isPropertyCall = (
lhs: ts.Node
): lhs is ts.PropertyAccessExpression & { expression: ts.Identifier; name: ts.Identifier } =>
ts.isPropertyAccessExpression(lhs) &&
ts.isIdentifier(lhs.expression) &&
ts.isIdentifier(lhs.name);
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/stackTraceParser.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Copied from https://github.com/microsoft/vscode-js-debug/blob/1d104b5184736677ab5cc280c70bbd227403850c/src/common/stackTraceParser.ts#L18
// Either match lines like
// " at fulfilled (/Users/roblou/code/testapp-node2/out/app.js:5:58)"
// or
// " at /Users/roblou/code/testapp-node2/out/app.js:60:23"
// and replace the path in them
const re1 = /^(\W*at .*\()(.*):(\d+):(\d+)(\))$/;
const re2 = /^(\W*at )(.*):(\d+):(\d+)$/;
const getLabelRe = /^\W*at (.*) \($/;
/**
* Parses a textual stack trace.
*/
export class StackTraceParser {
/** Gets whether the stacktrace has any locations in it. */
public static isStackLike(str: string) {
return re1.test(str) || re2.test(str);
}
constructor(private readonly stack: string) { }
/** Iterates over segments of text and locations in the stack. */
*[Symbol.iterator]() {
for (const line of this.stack.split('\n')) {
const match = re1.exec(line) || re2.exec(line);
if (!match) {
yield line + '\n';
continue;
}
const [, prefix, url, lineNo, columnNo, suffix] = match;
if (prefix) {
yield prefix;
}
yield new StackTraceLocation(getLabelRe.exec(prefix)?.[1], url, Number(lineNo), Number(columnNo));
if (suffix) {
yield suffix;
}
yield '\n';
}
}
}
export class StackTraceLocation {
constructor(
public readonly label: string | undefined,
public readonly path: string,
public readonly lineBase1: number,
public readonly columnBase1: number,
) { }
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/streamSplitter.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// DO NOT EDIT DIRECTLY: copied from src/vs/base/node/nodeStreams.ts
import { Transform } from 'stream';
/**
* A Transform stream that splits the input on the "splitter" substring.
* The resulting chunks will contain (and trail with) the splitter match.
* The last chunk when the stream ends will be emitted even if a splitter
* is not encountered.
*/
export class StreamSplitter extends Transform {
private buffer: Buffer | undefined;
private readonly splitter: number;
private readonly spitterLen: number;
constructor(splitter: string | number | Buffer) {
super();
if (typeof splitter === 'number') {
this.splitter = splitter;
this.spitterLen = 1;
} else {
throw new Error('not implemented here');
}
}
override _transform(
chunk: Buffer,
_encoding: string,
callback: (error?: Error | null, data?: any) => void
): void {
if (!this.buffer) {
this.buffer = chunk;
} else {
this.buffer = Buffer.concat([this.buffer, chunk]);
}
let offset = 0;
while (offset < this.buffer.length) {
const index = this.buffer.indexOf(this.splitter, offset);
if (index === -1) {
break;
}
this.push(this.buffer.slice(offset, index + this.spitterLen));
offset = index + this.spitterLen;
}
this.buffer = offset === this.buffer.length ? undefined : this.buffer.slice(offset);
callback();
}
override _flush(callback: (error?: Error | null, data?: any) => void): void {
if (this.buffer) {
this.push(this.buffer);
}
callback();
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/testOutputScanner.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import {
decodedMappings,
GREATEST_LOWER_BOUND,
LEAST_UPPER_BOUND,
originalPositionFor,
TraceMap,
} from '@jridgewell/trace-mapping';
import * as styles from 'ansi-styles';
import { ChildProcessWithoutNullStreams } from 'child_process';
import * as vscode from 'vscode';
import { istanbulCoverageContext, PerTestCoverageTracker } from './coverageProvider';
import { attachTestMessageMetadata } from './metadata';
import { snapshotComment } from './snapshot';
import { StackTraceLocation, StackTraceParser } from './stackTraceParser';
import { StreamSplitter } from './streamSplitter';
import { getContentFromFilesystem } from './testTree';
import { IScriptCoverage } from './v8CoverageWrangling';
export const enum MochaEvent {
Start = 'start',
TestStart = 'testStart',
Pass = 'pass',
Fail = 'fail',
End = 'end',
// custom events:
CoverageInit = 'coverageInit',
CoverageIncrement = 'coverageIncrement',
}
export interface IStartEvent {
total: number;
}
export interface ITestStartEvent {
title: string;
fullTitle: string;
file: string;
currentRetry: number;
speed: string;
}
export interface IPassEvent extends ITestStartEvent {
duration: number;
}
export interface IFailEvent extends IPassEvent {
err: string;
stack: string | null;
expected?: string;
actual?: string;
expectedJSON?: unknown;
actualJSON?: unknown;
snapshotPath?: string;
}
export interface IEndEvent {
suites: number;
tests: number;
passes: number;
pending: number;
failures: number;
start: string /* ISO date */;
end: string /* ISO date */;
}
export interface ITestCoverageCoverage {
file: string;
fullTitle: string;
coverage: { result: IScriptCoverage[] };
}
export type MochaEventTuple =
| [MochaEvent.Start, IStartEvent]
| [MochaEvent.TestStart, ITestStartEvent]
| [MochaEvent.Pass, IPassEvent]
| [MochaEvent.Fail, IFailEvent]
| [MochaEvent.End, IEndEvent]
| [MochaEvent.CoverageInit, { result: IScriptCoverage[] }]
| [MochaEvent.CoverageIncrement, ITestCoverageCoverage];
const LF = '\n'.charCodeAt(0);
export class TestOutputScanner implements vscode.Disposable {
protected mochaEventEmitter = new vscode.EventEmitter();
protected outputEventEmitter = new vscode.EventEmitter();
protected onExitEmitter = new vscode.EventEmitter();
/**
* Fired when a mocha event comes in.
*/
public readonly onMochaEvent = this.mochaEventEmitter.event;
/**
* Fired when other output from the process comes in.
*/
public readonly onOtherOutput = this.outputEventEmitter.event;
/**
* Fired when the process encounters an error, or exits.
*/
public readonly onRunnerExit = this.onExitEmitter.event;
constructor(private readonly process: ChildProcessWithoutNullStreams, private args?: string[]) {
process.stdout.pipe(new StreamSplitter(LF)).on('data', this.processData);
process.stderr.pipe(new StreamSplitter(LF)).on('data', this.processData);
process.on('error', e => this.onExitEmitter.fire(e.message));
process.on('exit', code =>
this.onExitEmitter.fire(code ? `Test process exited with code ${code}` : undefined)
);
}
/**
* @override
*/
public dispose() {
try {
this.process.kill();
} catch {
// ignored
}
}
protected readonly processData = (data: string | Buffer) => {
if (this.args) {
this.outputEventEmitter.fire(`./scripts/test ${this.args.join(' ')}`);
this.args = undefined;
}
data = data.toString();
try {
const parsed = JSON.parse(data.trim()) as unknown;
if (parsed instanceof Array && parsed.length === 2 && typeof parsed[0] === 'string') {
this.mochaEventEmitter.fire(parsed as MochaEventTuple);
} else {
this.outputEventEmitter.fire(data);
}
} catch {
this.outputEventEmitter.fire(data);
}
};
}
type QueuedOutput = string | [string, vscode.Location | undefined, vscode.TestItem | undefined];
export async function scanTestOutput(
tests: Map,
task: vscode.TestRun,
scanner: TestOutputScanner,
coverageDir: string | undefined,
cancellation: vscode.CancellationToken
): Promise {
const exitBlockers: Set> = new Set();
const skippedTests = new Set(tests.values());
const store = new SourceMapStore();
let outputQueue = Promise.resolve();
const enqueueOutput = (fn: QueuedOutput | (() => Promise)) => {
exitBlockers.delete(outputQueue);
outputQueue = outputQueue.finally(async () => {
const r = typeof fn === 'function' ? await fn() : fn;
typeof r === 'string' ? task.appendOutput(r) : task.appendOutput(...r);
});
exitBlockers.add(outputQueue);
return outputQueue;
};
const enqueueExitBlocker = (prom: Promise): Promise => {
exitBlockers.add(prom);
prom.finally(() => exitBlockers.delete(prom));
return prom;
};
let perTestCoverage: PerTestCoverageTracker | undefined;
let lastTest: vscode.TestItem | undefined;
let ranAnyTest = false;
try {
if (cancellation.isCancellationRequested) {
return;
}
await new Promise(resolve => {
cancellation.onCancellationRequested(() => {
resolve();
});
let currentTest: vscode.TestItem | undefined;
scanner.onRunnerExit(err => {
if (err) {
enqueueOutput(err + crlf);
}
resolve();
});
scanner.onOtherOutput(str => {
const match = spdlogRe.exec(str);
if (!match) {
enqueueOutput(str + crlf);
return;
}
const logLocation = store.getSourceLocation(match[2], Number(match[3]) - 1);
const logContents = replaceAllLocations(store, match[1]);
const test = currentTest;
enqueueOutput(() =>
Promise.all([logLocation, logContents]).then(([location, contents]) => [
contents + crlf,
location,
test,
])
);
});
scanner.onMochaEvent(evt => {
switch (evt[0]) {
case MochaEvent.Start:
break; // no-op
case MochaEvent.TestStart:
currentTest = tests.get(evt[1].fullTitle);
if (!currentTest) {
console.warn(`Could not find test ${evt[1].fullTitle}`);
return;
}
skippedTests.delete(currentTest);
task.started(currentTest);
ranAnyTest = true;
break;
case MochaEvent.Pass:
{
const title = evt[1].fullTitle;
const tcase = tests.get(title);
enqueueOutput(` ${styles.green.open}√${styles.green.close} ${title}\r\n`);
if (tcase) {
lastTest = tcase;
task.passed(tcase, evt[1].duration);
}
}
break;
case MochaEvent.Fail:
{
const {
err,
stack,
duration,
expected,
expectedJSON,
actual,
actualJSON,
snapshotPath,
fullTitle: id,
} = evt[1];
let tcase = tests.get(id);
// report failures on hook to the last-seen test, or first test if none run yet
if (!tcase && (id.includes('hook for') || id.includes('hook in'))) {
tcase = lastTest ?? tests.values().next().value;
}
enqueueOutput(`${styles.red.open} x ${id}${styles.red.close}\r\n`);
const rawErr = stack || err;
const locationsReplaced = replaceAllLocations(store, forceCRLF(rawErr));
if (rawErr) {
enqueueOutput(async () => [await locationsReplaced, undefined, tcase]);
}
if (!tcase) {
return;
}
const hasDiff =
actual !== undefined &&
expected !== undefined &&
(expected !== '[undefined]' || actual !== '[undefined]');
const testFirstLine =
tcase.range &&
new vscode.Location(
tcase.uri!,
new vscode.Range(
tcase.range.start,
new vscode.Position(tcase.range.start.line, 100)
)
);
enqueueExitBlocker(
(async () => {
const stackInfo = await deriveStackLocations(store, rawErr, tcase!);
let message: vscode.TestMessage;
if (hasDiff) {
message = new vscode.TestMessage(tryMakeMarkdown(err));
message.actualOutput = outputToString(actual);
message.expectedOutput = outputToString(expected);
if (snapshotPath) {
message.contextValue = 'isSelfhostSnapshotMessage';
message.expectedOutput += snapshotComment + snapshotPath;
}
attachTestMessageMetadata(message, {
expectedValue: expectedJSON,
actualValue: actualJSON,
});
} else {
message = new vscode.TestMessage(
stack ? await sourcemapStack(store, stack) : await locationsReplaced
);
}
message.location = stackInfo.primary ?? testFirstLine;
message.stackTrace = stackInfo.stack;
task.failed(tcase!, message, duration);
})()
);
}
break;
case MochaEvent.End:
// no-op, we wait until the process exits to ensure coverage is written out
break;
case MochaEvent.CoverageInit:
perTestCoverage ??= new PerTestCoverageTracker(store);
for (const result of evt[1].result) {
perTestCoverage.add(result);
}
break;
case MochaEvent.CoverageIncrement: {
const { fullTitle, coverage } = evt[1];
const tcase = tests.get(fullTitle);
if (tcase) {
perTestCoverage ??= new PerTestCoverageTracker(store);
for (const result of coverage.result) {
perTestCoverage.add(result, tcase);
}
}
break;
}
}
});
});
if (perTestCoverage) {
enqueueExitBlocker(perTestCoverage.report(task));
}
await Promise.all([...exitBlockers]);
if (coverageDir) {
try {
await istanbulCoverageContext.apply(task, coverageDir, {
mapFileUri: uri => store.getSourceFile(uri.toString()),
mapLocation: (uri, position) =>
store.getSourceLocation(uri.toString(), position.line, position.character),
});
} catch (e) {
const msg = `Error loading coverage:\n\n${e}\n`;
task.appendOutput(msg.replace(/\n/g, crlf));
}
}
// no tests? Possible crash, show output:
if (!ranAnyTest) {
await vscode.commands.executeCommand('testing.showMostRecentOutput');
}
} catch (e) {
task.appendOutput((e as Error).stack || (e as Error).message);
} finally {
scanner.dispose();
for (const test of skippedTests) {
task.skipped(test);
}
task.end();
}
}
const spdlogRe = /"(.+)", source: (file:\/\/\/.*?)+ \(([0-9]+)\)/;
const crlf = '\r\n';
const forceCRLF = (str: string) => str.replace(/(? {
locationRe.lastIndex = 0;
const replacements = await Promise.all(
[...str.matchAll(locationRe)].map(async match => {
const location = await deriveSourceLocation(store, match);
if (!location) {
return;
}
return {
from: match[0],
to: location?.uri.with({
fragment: `L${location.range.start.line + 1}:${location.range.start.character + 1}`,
}),
};
})
);
for (const replacement of replacements) {
if (replacement) {
str = str.replace(replacement.from, replacement.to.toString(true));
}
}
return str;
};
const outputToString = (output: unknown) =>
typeof output === 'object' ? JSON.stringify(output, null, 2) : String(output);
const tryMakeMarkdown = (message: string) => {
const lines = message.split('\n');
const start = lines.findIndex(l => l.includes('+ actual'));
if (start === -1) {
return message;
}
lines.splice(start, 1, '```diff');
lines.push('```');
return new vscode.MarkdownString(lines.join('\n'));
};
const inlineSourcemapRe = /^\/\/# sourceMappingURL=data:application\/json;base64,(.+)/m;
const sourceMapBiases = [GREATEST_LOWER_BOUND, LEAST_UPPER_BOUND] as const;
export const enum SearchStrategy {
FirstBefore = -1,
FirstAfter = 1,
}
export type SourceLocationMapper = (line: number, col: number, strategy: SearchStrategy) => vscode.Location | undefined;
export class SourceMapStore {
private readonly cache = new Map* file uri */ string, Promise>();
async getSourceLocationMapper(fileUri: string): Promise {
const sourceMap = await this.loadSourceMap(fileUri);
return (line, col, strategy) => {
if (!sourceMap) {
return undefined;
}
// 1. Look for the ideal position on this line if it exists
const idealPosition = originalPositionFor(sourceMap, { column: col, line: line + 1, bias: SearchStrategy.FirstAfter ? GREATEST_LOWER_BOUND : LEAST_UPPER_BOUND });
if (idealPosition.line !== null && idealPosition.column !== null && idealPosition.source !== null) {
return new vscode.Location(
this.completeSourceMapUrl(sourceMap, idealPosition.source),
new vscode.Position(idealPosition.line - 1, idealPosition.column)
);
}
// Otherwise get the first/last valid mapping on another line.
const decoded = decodedMappings(sourceMap);
const enum MapField {
COLUMN = 0,
SOURCES_INDEX = 1,
SOURCE_LINE = 2,
SOURCE_COLUMN = 3,
}
do {
line += strategy;
const segments = decoded[line];
if (!segments?.length) {
continue;
}
const index = strategy === SearchStrategy.FirstBefore
? findLastIndex(segments, s => s.length !== 1)
: segments.findIndex(s => s.length !== 1);
const segment = segments[index];
if (!segment || segment.length === 1) {
continue;
}
return new vscode.Location(
this.completeSourceMapUrl(sourceMap, sourceMap.sources[segment[MapField.SOURCES_INDEX]]!),
new vscode.Position(segment[MapField.SOURCE_LINE] - 1, segment[MapField.SOURCE_COLUMN])
);
} while (strategy === SearchStrategy.FirstBefore ? line > 0 : line < decoded.length);
return undefined;
};
}
/** Gets an original location from a base 0 line and column */
async getSourceLocation(fileUri: string, line: number, col = 0) {
const sourceMap = await this.loadSourceMap(fileUri);
if (!sourceMap) {
return undefined;
}
let smLine = line + 1;
// if the range is after the end of mappings, adjust it to the last mapped line
const decoded = decodedMappings(sourceMap);
if (decoded.length <= line) {
smLine = decoded.length; // base 1, no -1 needed
col = Number.MAX_SAFE_INTEGER;
}
for (const bias of sourceMapBiases) {
const position = originalPositionFor(sourceMap, { column: col, line: smLine, bias });
if (position.line !== null && position.column !== null && position.source !== null) {
return new vscode.Location(
this.completeSourceMapUrl(sourceMap, position.source),
new vscode.Position(position.line - 1, position.column)
);
}
}
return undefined;
}
async getSourceFile(compiledUri: string) {
const sourceMap = await this.loadSourceMap(compiledUri);
if (!sourceMap) {
return undefined;
}
if (sourceMap.sources[0]) {
return this.completeSourceMapUrl(sourceMap, sourceMap.sources[0]);
}
for (const bias of sourceMapBiases) {
const position = originalPositionFor(sourceMap, { column: 0, line: 1, bias });
if (position.source !== null) {
return this.completeSourceMapUrl(sourceMap, position.source);
}
}
return undefined;
}
private completeSourceMapUrl(sm: TraceMap, source: string) {
if (sm.sourceRoot) {
try {
return vscode.Uri.parse(new URL(source, sm.sourceRoot).toString());
} catch {
// ignored
}
}
return vscode.Uri.parse(source);
}
private loadSourceMap(fileUri: string) {
const existing = this.cache.get(fileUri);
if (existing) {
return existing;
}
const promise = (async () => {
try {
const contents = await getContentFromFilesystem(vscode.Uri.parse(fileUri));
const sourcemapMatch = inlineSourcemapRe.exec(contents);
if (!sourcemapMatch) {
return;
}
const decoded = Buffer.from(sourcemapMatch[1], 'base64').toString();
return new TraceMap(decoded, fileUri);
} catch (e) {
console.warn(`Error parsing sourcemap for ${fileUri}: ${(e as Error).stack}`);
return;
}
})();
this.cache.set(fileUri, promise);
return promise;
}
}
const locationRe = /(file:\/{3}.+):([0-9]+):([0-9]+)/g;
async function replaceAllLocations(store: SourceMapStore, str: string) {
const output: (string | Promise)[] = [];
let lastIndex = 0;
for (const match of str.matchAll(locationRe)) {
const locationPromise = deriveSourceLocation(store, match);
const startIndex = match.index || 0;
const endIndex = startIndex + match[0].length;
if (startIndex > lastIndex) {
output.push(str.substring(lastIndex, startIndex));
}
output.push(
locationPromise.then(location =>
location
? `${location.uri}:${location.range.start.line + 1}:${location.range.start.character + 1}`
: match[0]
)
);
lastIndex = endIndex;
}
// Preserve the remaining string after the last match
if (lastIndex < str.length) {
output.push(str.substring(lastIndex));
}
const values = await Promise.all(output);
return values.join('');
}
async function deriveStackLocations(
store: SourceMapStore,
stack: string,
tcase: vscode.TestItem
) {
locationRe.lastIndex = 0;
const locationsRaw = [...new StackTraceParser(stack)].filter(t => t instanceof StackTraceLocation);
const locationsMapped = await Promise.all(locationsRaw.map(async location => {
const mapped = location.path.startsWith('file:') ? await store.getSourceLocation(location.path, location.lineBase1 - 1, location.columnBase1 - 1) : undefined;
const stack = new vscode.TestMessageStackFrame(location.label || '', mapped?.uri, mapped?.range.start || new vscode.Position(location.lineBase1 - 1, location.columnBase1 - 1));
return { location: mapped, stack };
}));
let best: undefined | { location: vscode.Location; score: number };
for (const { location } of locationsMapped) {
if (!location) {
continue;
}
let score = 0;
if (tcase.uri && tcase.uri.toString() === location.uri.toString()) {
score = 1;
if (tcase.range && tcase.range.contains(location?.range)) {
score = 2;
}
}
if (!best || score > best.score) {
best = { location, score };
}
}
return { stack: locationsMapped.map(s => s.stack), primary: best?.location };
}
async function deriveSourceLocation(store: SourceMapStore, parts: RegExpMatchArray) {
const [, fileUri, line, col] = parts;
return store.getSourceLocation(fileUri, Number(line) - 1, Number(col));
}
function findLastIndex(arr: T[], predicate: (value: T) => boolean) {
for (let i = arr.length - 1; i >= 0; i--) {
if (predicate(arr[i])) {
return i;
}
}
return -1;
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/testTree.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { join, relative } from 'path';
import * as ts from 'typescript';
import { TextDecoder } from 'util';
import * as vscode from 'vscode';
import { Action, extractTestFromNode } from './sourceUtils';
const textDecoder = new TextDecoder('utf-8');
const diagnosticCollection = vscode.languages.createDiagnosticCollection('selfhostTestProvider');
type ContentGetter = (uri: vscode.Uri) => Promise;
export const itemData = new WeakMap();
export const clearFileDiagnostics = (uri: vscode.Uri) => diagnosticCollection.delete(uri);
/**
* Tries to guess which workspace folder VS Code is in.
*/
export const guessWorkspaceFolder = async () => {
if (!vscode.workspace.workspaceFolders) {
return undefined;
}
if (vscode.workspace.workspaceFolders.length < 2) {
return vscode.workspace.workspaceFolders[0];
}
for (const folder of vscode.workspace.workspaceFolders) {
try {
await vscode.workspace.fs.stat(vscode.Uri.joinPath(folder.uri, 'src/vs/loader.js'));
return folder;
} catch {
// ignored
}
}
return undefined;
};
export const getContentFromFilesystem: ContentGetter = async uri => {
try {
const rawContent = await vscode.workspace.fs.readFile(uri);
return textDecoder.decode(rawContent);
} catch (e) {
console.warn(`Error providing tests for ${uri.fsPath}`, e);
return '';
}
};
export class TestFile {
public hasBeenRead = false;
constructor(
public readonly uri: vscode.Uri,
public readonly workspaceFolder: vscode.WorkspaceFolder
) {}
public getId() {
return this.uri.toString().toLowerCase();
}
public getLabel() {
return relative(join(this.workspaceFolder.uri.fsPath, 'src'), this.uri.fsPath);
}
public async updateFromDisk(controller: vscode.TestController, item: vscode.TestItem) {
try {
const content = await getContentFromFilesystem(item.uri!);
item.error = undefined;
this.updateFromContents(controller, content, item);
} catch (e) {
item.error = (e as Error).stack;
}
}
/**
* Refreshes all tests in this file, `sourceReader` provided by the root.
*/
public updateFromContents(
controller: vscode.TestController,
content: string,
file: vscode.TestItem
) {
try {
const diagnostics: vscode.Diagnostic[] = [];
const ast = ts.createSourceFile(
this.uri.path.split('/').pop()!,
content,
ts.ScriptTarget.ESNext,
false,
ts.ScriptKind.TS
);
const parents: { item: vscode.TestItem; children: vscode.TestItem[] }[] = [
{ item: file, children: [] },
];
const traverse = (node: ts.Node) => {
const parent = parents[parents.length - 1];
const childData = extractTestFromNode(ast, node, itemData.get(parent.item)!);
if (childData === Action.Skip) {
return;
}
if (childData === Action.Recurse) {
ts.forEachChild(node, traverse);
return;
}
const id = `${file.uri}/${childData.fullName}`.toLowerCase();
// Skip duplicated tests. They won't run correctly with the way
// mocha reports them, and will error if we try to insert them.
const existing = parent.children.find(c => c.id === id);
if (existing) {
const diagnostic = new vscode.Diagnostic(
childData.range,
'Duplicate tests cannot be run individually and will not be reported correctly by the test framework. Please rename them.',
vscode.DiagnosticSeverity.Warning
);
diagnostic.relatedInformation = [
new vscode.DiagnosticRelatedInformation(
new vscode.Location(existing.uri!, existing.range!),
'First declared here'
),
];
diagnostics.push(diagnostic);
return;
}
const item = controller.createTestItem(id, childData.name, file.uri);
itemData.set(item, childData);
item.range = childData.range;
parent.children.push(item);
if (childData instanceof TestSuite) {
parents.push({ item: item, children: [] });
ts.forEachChild(node, traverse);
item.children.replace(parents.pop()!.children);
}
};
ts.forEachChild(ast, traverse);
file.error = undefined;
file.children.replace(parents[0].children);
diagnosticCollection.set(this.uri, diagnostics.length ? diagnostics : undefined);
this.hasBeenRead = true;
} catch (e) {
file.error = String((e as Error).stack || (e as Error).message);
}
}
}
export abstract class TestConstruct {
public fullName: string;
constructor(
public readonly name: string,
public readonly range: vscode.Range,
parent?: TestConstruct
) {
this.fullName = parent ? `${parent.fullName} ${name}` : name;
}
}
export class TestSuite extends TestConstruct {}
export class TestCase extends TestConstruct {}
export type VSCodeTest = TestFile | TestSuite | TestCase;
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/v8CoverageWrangling.test.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 assert from 'assert';
import { RangeCoverageTracker } from './v8CoverageWrangling';
suite('v8CoverageWrangling', () => {
suite('RangeCoverageTracker', () => {
test('covers new range', () => {
const rt = new RangeCoverageTracker();
rt.cover(5, 10);
assert.deepStrictEqual([...rt], [{ start: 5, end: 10, covered: true }]);
});
test('non overlapping ranges', () => {
const rt = new RangeCoverageTracker();
rt.cover(5, 10);
rt.cover(15, 20);
rt.cover(12, 13);
assert.deepStrictEqual(
[...rt],
[
{ start: 5, end: 10, covered: true },
{ start: 12, end: 13, covered: true },
{ start: 15, end: 20, covered: true },
]
);
});
test('covers exact', () => {
const rt = new RangeCoverageTracker();
rt.uncovered(5, 10);
rt.cover(5, 10);
assert.deepStrictEqual([...rt], [{ start: 5, end: 10, covered: true }]);
});
test('overlap at start', () => {
const rt = new RangeCoverageTracker();
rt.uncovered(5, 10);
rt.cover(2, 7);
assert.deepStrictEqual(
[...rt],
[
{ start: 2, end: 7, covered: true },
{ start: 7, end: 10, covered: false },
]
);
});
test('overlap at end', () => {
const rt = new RangeCoverageTracker();
rt.cover(5, 10);
rt.uncovered(2, 7);
assert.deepStrictEqual(
[...rt],
[
{ start: 2, end: 5, covered: false },
{ start: 5, end: 10, covered: true },
]
);
});
test('inner contained', () => {
const rt = new RangeCoverageTracker();
rt.cover(5, 10);
rt.uncovered(2, 12);
assert.deepStrictEqual(
[...rt],
[
{ start: 2, end: 5, covered: false },
{ start: 5, end: 10, covered: true },
{ start: 10, end: 12, covered: false },
]
);
});
test('outer contained', () => {
const rt = new RangeCoverageTracker();
rt.uncovered(5, 10);
rt.cover(7, 9);
assert.deepStrictEqual(
[...rt],
[
{ start: 5, end: 7, covered: false },
{ start: 7, end: 9, covered: true },
{ start: 9, end: 10, covered: false },
]
);
});
test('boundary touching', () => {
const rt = new RangeCoverageTracker();
rt.uncovered(5, 10);
rt.cover(10, 15);
rt.uncovered(15, 20);
assert.deepStrictEqual(
[...rt],
[
{ start: 5, end: 10, covered: false },
{ start: 10, end: 15, covered: true },
{ start: 15, end: 20, covered: false },
]
);
});
suite('initializeBlock', () => {
test('simple tree', () => {
const rt = RangeCoverageTracker.initializeBlocks([
{
functionName: 'outer',
isBlockCoverage: true,
ranges: [
{ count: 1, startOffset: 5, endOffset: 30 },
{ count: 1, startOffset: 8, endOffset: 10 },
{ count: 0, startOffset: 15, endOffset: 20 },
],
},
]);
assert.deepStrictEqual(
[...rt],
[
{ start: 5, end: 15, covered: true },
{ start: 15, end: 20, covered: false },
{ start: 20, end: 30, covered: true },
]
);
});
test('separate branches', () => {
const rt = RangeCoverageTracker.initializeBlocks([
{
functionName: 'outer',
isBlockCoverage: true,
ranges: [
{ count: 1, startOffset: 5, endOffset: 8 },
{ count: 1, startOffset: 10, endOffset: 12 },
{ count: 0, startOffset: 15, endOffset: 20 },
],
},
]);
assert.deepStrictEqual(
[...rt],
[
{ start: 5, end: 8, covered: true },
{ start: 10, end: 12, covered: true },
{ start: 15, end: 20, covered: false },
]
);
});
});
});
});
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/v8CoverageWrangling.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface ICoverageRange {
start: number;
end: number;
covered: boolean;
}
export interface IV8FunctionCoverage {
functionName: string;
isBlockCoverage: boolean;
ranges: IV8CoverageRange[];
}
export interface IV8CoverageRange {
startOffset: number;
endOffset: number;
count: number;
}
/** V8 Script coverage data */
export interface IScriptCoverage {
scriptId: string;
url: string;
// Script source added by the runner the first time the script is emitted.
source?: string;
functions: IV8FunctionCoverage[];
}
export class RangeCoverageTracker implements Iterable {
/**
* A noncontiguous, non-overlapping, ordered set of ranges and whether
* that range has been covered.
*/
private ranges: readonly ICoverageRange[] = [];
/**
* Adds a coverage tracker initialized for a function with {@link isBlockCoverage} set to true.
*/
public static initializeBlocks(fns: IV8FunctionCoverage[]) {
const rt = new RangeCoverageTracker();
let start = 0;
const stack: IV8CoverageRange[] = [];
// note: comes pre-sorted from V8
for (const { ranges } of fns) {
for (const range of ranges) {
while (stack.length && stack[stack.length - 1].endOffset < range.startOffset) {
const last = stack.pop()!;
rt.setCovered(start, last.endOffset, last.count > 0);
start = last.endOffset;
}
if (range.startOffset > start && stack.length) {
rt.setCovered(start, range.startOffset, !!stack[stack.length - 1].count);
}
start = range.startOffset;
stack.push(range);
}
}
while (stack.length) {
const last = stack.pop()!;
rt.setCovered(start, last.endOffset, last.count > 0);
start = last.endOffset;
}
return rt;
}
/** Makes a copy of the range tracker. */
public clone() {
const rt = new RangeCoverageTracker();
rt.ranges = this.ranges.slice();
return rt;
}
/** Marks a range covered */
public cover(start: number, end: number) {
this.setCovered(start, end, true);
}
/** Marks a range as uncovered */
public uncovered(start: number, end: number) {
this.setCovered(start, end, false);
}
/** Iterates over coverage ranges */
[Symbol.iterator]() {
return this.ranges[Symbol.iterator]();
}
/**
* Marks the given character range as being covered or uncovered.
*
* todo@connor4312: this is a hot path is could probably be optimized to
* avoid rebuilding the array. Maybe with a nice tree structure?
*/
public setCovered(start: number, end: number, covered: boolean) {
const newRanges: ICoverageRange[] = [];
let i = 0;
for (; i < this.ranges.length && this.ranges[i].end <= start; i++) {
newRanges.push(this.ranges[i]);
}
const push = (range: ICoverageRange) => {
const last = newRanges.length && newRanges[newRanges.length - 1];
if (last && last.end === range.start && last.covered === range.covered) {
last.end = range.end;
} else {
newRanges.push(range);
}
};
push({ start, end, covered });
for (; i < this.ranges.length; i++) {
const range = this.ranges[i];
const last = newRanges[newRanges.length - 1];
if (range.start === last.start && range.end === last.end) {
// ranges are equal:
last.covered ||= range.covered;
} else if (range.end < last.start || range.start > last.end) {
// ranges don't overlap
push(range);
} else if (range.start < last.start && range.end > last.end) {
// range contains last:
newRanges.pop();
push({ start: range.start, end: last.start, covered: range.covered });
push({ start: last.start, end: last.end, covered: range.covered || last.covered });
push({ start: last.end, end: range.end, covered: range.covered });
} else if (range.start >= last.start && range.end <= last.end) {
// last contains range:
newRanges.pop();
push({ start: last.start, end: range.start, covered: last.covered });
push({ start: range.start, end: range.end, covered: range.covered || last.covered });
push({ start: range.end, end: last.end, covered: last.covered });
} else if (range.start < last.start && range.end <= last.end) {
// range overlaps start of last:
newRanges.pop();
push({ start: range.start, end: last.start, covered: range.covered });
push({ start: last.start, end: range.end, covered: range.covered || last.covered });
push({ start: range.end, end: last.end, covered: last.covered });
} else if (range.start >= last.start && range.end > last.end) {
// range overlaps end of last:
newRanges.pop();
push({ start: last.start, end: range.start, covered: last.covered });
push({ start: range.start, end: last.end, covered: range.covered || last.covered });
push({ start: last.end, end: range.end, covered: range.covered });
} else {
throw new Error('unreachable');
}
}
this.ranges = newRanges;
}
}
export class OffsetToPosition {
/** Line numbers to byte offsets. */
public readonly lines: number[] = [];
public readonly totalLength: number;
constructor(source: string) {
this.lines.push(0);
for (let i = source.indexOf('\n'); i !== -1; i = source.indexOf('\n', i + 1)) {
this.lines.push(i + 1);
}
this.totalLength = source.length;
}
public getLineLength(lineNumber: number): number {
return (
(lineNumber < this.lines.length - 1 ? this.lines[lineNumber + 1] - 1 : this.totalLength) -
this.lines[lineNumber]
);
}
/**
* Gets the line the offset appears on.
*/
public getLineOfOffset(offset: number): number {
let low = 0;
let high = this.lines.length;
while (low < high) {
const mid = Math.floor((low + high) / 2);
if (this.lines[mid] > offset) {
high = mid;
} else {
low = mid + 1;
}
}
return low - 1;
}
/**
* Converts from a file offset to a base 0 line/column .
*/
public toLineColumn(offset: number): { line: number; column: number } {
const line = this.getLineOfOffset(offset);
return { line: line, column: offset - this.lines[line] };
}
}
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/src/vscodeTestRunner.ts
================================================
/*---------------------------------------------------------------------------------------------
* 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 { AddressInfo, createServer } from 'net';
import * as path from 'path';
import * as vscode from 'vscode';
import { TestOutputScanner } from './testOutputScanner';
import { TestCase, TestFile, TestSuite, itemData } from './testTree';
/**
* From MDN
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
*/
const escapeRe = (s: string) => s.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
const TEST_ELECTRON_SCRIPT_PATH = 'test/unit/electron/index.js';
const TEST_BROWSER_SCRIPT_PATH = 'test/unit/browser/index.js';
const ATTACH_CONFIG_NAME = 'Attach to VS Code';
const DEBUG_TYPE = 'pwa-chrome';
export abstract class VSCodeTestRunner {
constructor(protected readonly repoLocation: vscode.WorkspaceFolder) { }
public async run(baseArgs: ReadonlyArray, filter?: ReadonlyArray) {
const args = this.prepareArguments(baseArgs, filter);
const cp = spawn(await this.binaryPath(), args, {
cwd: this.repoLocation.uri.fsPath,
stdio: 'pipe',
env: this.getEnvironment(),
});
return new TestOutputScanner(cp, args);
}
public async debug(testRun: vscode.TestRun, baseArgs: ReadonlyArray, filter?: ReadonlyArray) {
const port = await this.findOpenPort();
const baseConfiguration = vscode.workspace
.getConfiguration('launch', this.repoLocation)
.get('configurations', [])
.find(c => c.name === ATTACH_CONFIG_NAME);
if (!baseConfiguration) {
throw new Error(`Could not find launch configuration ${ATTACH_CONFIG_NAME}`);
}
const server = this.createWaitServer();
const args = [
...this.prepareArguments(baseArgs, filter),
`--remote-debugging-port=${port}`,
// for breakpoint freeze: https://github.com/microsoft/vscode/issues/122225#issuecomment-885377304
'--js-flags="--regexp_interpret_all"',
// for general runtime freezes: https://github.com/microsoft/vscode/issues/127861#issuecomment-904144910
'--disable-features=CalculateNativeWinOcclusion',
'--timeout=0',
`--waitServer=${server.port}`,
];
const cp = spawn(await this.binaryPath(), args, {
cwd: this.repoLocation.uri.fsPath,
stdio: 'pipe',
env: this.getEnvironment(port),
});
// Register a descriptor factory that signals the server when any
// breakpoint set requests on the debugee have been completed.
const factory = vscode.debug.registerDebugAdapterTrackerFactory(DEBUG_TYPE, {
createDebugAdapterTracker(session) {
if (!session.parentSession || session.parentSession !== rootSession) {
return;
}
let initRequestId: number | undefined;
return {
onDidSendMessage(message) {
if (message.type === 'response' && message.request_seq === initRequestId) {
server.ready();
}
},
onWillReceiveMessage(message) {
if (initRequestId !== undefined) {
return;
}
if (message.command === 'launch' || message.command === 'attach') {
initRequestId = message.seq;
}
},
};
},
});
vscode.debug.startDebugging(this.repoLocation, { ...baseConfiguration, port }, { testRun });
let exited = false;
let rootSession: vscode.DebugSession | undefined;
cp.once('exit', () => {
exited = true;
server.dispose();
listener.dispose();
factory.dispose();
if (rootSession) {
vscode.debug.stopDebugging(rootSession);
}
});
const listener = vscode.debug.onDidStartDebugSession(s => {
if (s.name === ATTACH_CONFIG_NAME && !rootSession) {
if (exited) {
vscode.debug.stopDebugging(rootSession);
} else {
rootSession = s;
}
}
});
return new TestOutputScanner(cp, args);
}
private findOpenPort(): Promise {
return new Promise((resolve, reject) => {
const server = createServer();
server.listen(0, () => {
const address = server.address() as AddressInfo;
const port = address.port;
server.close(() => {
resolve(port);
});
});
server.on('error', (error: Error) => {
reject(error);
});
});
}
protected getEnvironment(_remoteDebugPort?: number): NodeJS.ProcessEnv {
return {
...process.env,
ELECTRON_RUN_AS_NODE: undefined,
ELECTRON_ENABLE_LOGGING: '1',
};
}
private prepareArguments(
baseArgs: ReadonlyArray,
filter?: ReadonlyArray
) {
const args = [...this.getDefaultArgs(), ...baseArgs, '--reporter', 'full-json-stream'];
if (!filter) {
return args;
}
const grepRe: string[] = [];
const runPaths = new Set();
const addTestFileRunPath = (data: TestFile) =>
runPaths.add(
path.relative(data.workspaceFolder.uri.fsPath, data.uri.fsPath).replace(/\\/g, '/')
);
const itemDatas = filter.map(f => itemData.get(f));
/** If true, we have to be careful with greps, as a grep for one test file affects the run of the other test file. */
const hasBothTestCaseOrTestSuiteAndTestFileFilters =
itemDatas.some(d => (d instanceof TestCase) || (d instanceof TestSuite)) &&
itemDatas.some(d => d instanceof TestFile);
function addTestCaseOrSuite(data: TestCase | TestSuite, test: vscode.TestItem): void {
grepRe.push(escapeRe(data.fullName) + (data instanceof TestCase ? '$' : ' '));
for (let p = test.parent; p; p = p.parent) {
const parentData = itemData.get(p);
if (parentData instanceof TestFile) {
addTestFileRunPath(parentData);
}
}
}
for (const test of filter) {
const data = itemData.get(test);
if (data instanceof TestCase || data instanceof TestSuite) {
addTestCaseOrSuite(data, test);
} else if (data instanceof TestFile) {
if (!hasBothTestCaseOrTestSuiteAndTestFileFilters) {
addTestFileRunPath(data);
} else {
// We add all the items individually so they get their own grep expressions.
for (const [_id, nestedTest] of test.children) {
const childData = itemData.get(nestedTest);
if (childData instanceof TestCase || childData instanceof TestSuite) {
addTestCaseOrSuite(childData, nestedTest);
} else {
console.error('Unexpected test item in test file', nestedTest.id, nestedTest.label);
}
}
}
}
}
if (grepRe.length) {
args.push('--grep', `/^(${grepRe.join('|')})/`);
}
if (runPaths.size) {
args.push(...[...runPaths].flatMap(p => ['--run', p]));
}
return args;
}
protected abstract getDefaultArgs(): string[];
protected abstract binaryPath(): Promise;
protected async readProductJson() {
const projectJson = await fs.readFile(
path.join(this.repoLocation.uri.fsPath, 'product.json'),
'utf-8'
);
try {
return JSON.parse(projectJson);
} catch (e) {
throw new Error(`Error parsing product.json: ${(e as Error).message}`);
}
}
private createWaitServer() {
const onReady = new vscode.EventEmitter();
let ready = false;
const server = createServer(socket => {
if (ready) {
socket.end();
} else {
onReady.event(() => socket.end());
}
});
server.listen(0);
return {
port: (server.address() as AddressInfo).port,
ready: () => {
ready = true;
onReady.fire();
},
dispose: () => {
server.close();
},
};
}
}
export class BrowserTestRunner extends VSCodeTestRunner {
/** @override */
protected binaryPath(): Promise {
return Promise.resolve(process.execPath);
}
/** @override */
protected override getEnvironment(remoteDebugPort?: number) {
return {
...super.getEnvironment(remoteDebugPort),
PLAYWRIGHT_CHROMIUM_DEBUG_PORT: remoteDebugPort ? String(remoteDebugPort) : undefined,
ELECTRON_RUN_AS_NODE: '1',
};
}
/** @override */
protected getDefaultArgs() {
return [TEST_BROWSER_SCRIPT_PATH];
}
}
export class WindowsTestRunner extends VSCodeTestRunner {
/** @override */
protected async binaryPath() {
const { nameShort } = await this.readProductJson();
return path.join(this.repoLocation.uri.fsPath, `.build/electron/${nameShort}.exe`);
}
/** @override */
protected getDefaultArgs() {
return [TEST_ELECTRON_SCRIPT_PATH];
}
}
export class PosixTestRunner extends VSCodeTestRunner {
/** @override */
protected async binaryPath() {
const { applicationName } = await this.readProductJson();
return path.join(this.repoLocation.uri.fsPath, `.build/electron/${applicationName}`);
}
/** @override */
protected getDefaultArgs() {
return [TEST_ELECTRON_SCRIPT_PATH];
}
}
export class DarwinTestRunner extends PosixTestRunner {
/** @override */
protected override getDefaultArgs() {
return [
TEST_ELECTRON_SCRIPT_PATH,
'--no-sandbox',
'--disable-dev-shm-usage',
'--use-gl=swiftshader',
];
}
/** @override */
protected override async binaryPath() {
const { nameLong } = await this.readProductJson();
return path.join(
this.repoLocation.uri.fsPath,
`.build/electron/${nameLong}.app/Contents/MacOS/Electron`
);
}
}
export const PlatformTestRunner =
process.platform === 'win32'
? WindowsTestRunner
: process.platform === 'darwin'
? DarwinTestRunner
: PosixTestRunner;
================================================
FILE: .vscode/extensions/vscode-selfhost-test-provider/tsconfig.json
================================================
{
"extends": "../../../extensions/tsconfig.base.json",
"compilerOptions": {
"outDir": "./out",
"types": [
"node",
"mocha",
]
},
"include": [
"src/**/*",
"../../../src/vscode-dts/vscode.d.ts",
"../../../src/vscode-dts/vscode.proposed.testObserver.d.ts",
"../../../src/vscode-dts/vscode.proposed.testRelatedCode.d.ts"
]
}
================================================
FILE: .vscode/extensions.json
================================================
{
// See https://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"github.vscode-pull-request-github",
"ms-vscode.vscode-github-issue-notebooks",
"ms-vscode.extension-test-runner",
"jrieken.vscode-pr-pinger"
]
}
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.1.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Gulp Build",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"stopOnEntry": true,
"args": [
"hygiene"
]
},
{
"type": "node",
"request": "attach",
"restart": true,
"name": "Attach to Extension Host",
"timeout": 0,
"port": 5870,
"outFiles": [
"${workspaceFolder}/out/**/*.js",
"${workspaceFolder}/extensions/*/out/**/*.js"
]
},
{
"type": "node",
"request": "attach",
"restart": true,
"name": "Attach to Shared Process",
"timeout": 0,
"port": 5879,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Search Process",
"port": 5876,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Pty Host Process",
"port": 5877,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
},
{
"type": "node",
"request": "attach",
"name": "Attach to CLI Process",
"port": 5874,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Main Process",
"timeout": 30000,
"port": 5875,
"continueOnAttach": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"hidden": true,
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code Emmet Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/emmet/test-workspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/emmet",
"--extensionTestsPath=${workspaceFolder}/extensions/emmet/out/test"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 6
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code Configuration Editing Tests",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/extensions/configuration-editing",
"--extensionTestsPath=${workspaceFolder}/extensions/configuration-editing/out/test"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 6
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code Git Tests",
"runtimeExecutable": "${execPath}",
"args": [
"/tmp/my4g9l",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/git",
"--extensionTestsPath=${workspaceFolder}/extensions/git/out/test"
],
"outFiles": [
"${workspaceFolder}/extensions/git/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 6
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code Github Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/github/testWorkspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/github",
"--extensionTestsPath=${workspaceFolder}/extensions/github/out/test"
],
"outFiles": [
"${workspaceFolder}/extensions/github/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 6
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code API Tests (single folder)",
"runtimeExecutable": "${execPath}",
"args": [
// "${workspaceFolder}", // Uncomment for running out of sources.
"${workspaceFolder}/extensions/vscode-api-tests/testWorkspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-api-tests",
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out/singlefolder-tests",
"--disable-extensions"
],
"outFiles": [
"${workspaceFolder}/extensions/vscode-api-tests/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 3
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code API Tests (workspace)",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/vscode-api-tests/testworkspace.code-workspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-api-tests",
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out/workspace-tests"
],
"outFiles": [
"${workspaceFolder}/extensions/vscode-api-tests/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 4
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code Tokenizer Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/vscode-colorize-tests/test",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-colorize-tests",
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-colorize-tests/out"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 5
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "VS Code Tokenizer Performance Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/vscode-colorize-perf-tests/test",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-colorize-perf-tests",
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-colorize-perf-tests/out"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 6
}
},
{
"type": "chrome",
"request": "attach",
"name": "Attach to VS Code",
"browserAttachLocation": "workspace",
"port": 9222,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/out/**/*.js"
],
"perScriptSourcemaps": "yes"
},
{
"type": "chrome",
"request": "launch",
"name": "Launch VS Code Internal",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.bat"
},
"osx": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
},
"port": 9222,
"timeout": 0,
"env": {
"VSCODE_EXTHOST_WILL_SEND_SOCKET": null,
"VSCODE_SKIP_PRELAUNCH": "1",
},
"cleanUp": "wholeBrowser",
"runtimeArgs": [
"--inspect-brk=5875",
"--no-cached-data",
"--crash-reporter-directory=${workspaceFolder}/.profile-oss/crashes",
// for general runtime freezes: https://github.com/microsoft/vscode/issues/127861#issuecomment-904144910
"--disable-features=CalculateNativeWinOcclusion",
"--disable-extension=vscode.vscode-api-tests"
],
"userDataDir": "${userHome}/.vscode-oss-dev",
"webRoot": "${workspaceFolder}",
"cascadeTerminateToConfigurations": [
"Attach to Extension Host"
],
"pauseForSourceMap": false,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"browserLaunchLocation": "workspace",
"presentation": {
"hidden": true,
},
},
{
// To debug observables you also need the extension "ms-vscode.debug-value-editor"
"type": "chrome",
"request": "launch",
"name": "Launch VS Code Internal (Dev Debug)",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.bat"
},
"osx": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
},
"port": 9222,
"timeout": 0,
"env": {
"VSCODE_EXTHOST_WILL_SEND_SOCKET": null,
"VSCODE_SKIP_PRELAUNCH": "1",
"VSCODE_DEV_DEBUG": "1",
},
"cleanUp": "wholeBrowser",
"runtimeArgs": [
"--inspect-brk=5875",
"--no-cached-data",
"--crash-reporter-directory=${workspaceFolder}/.profile-oss/crashes",
// for general runtime freezes: https://github.com/microsoft/vscode/issues/127861#issuecomment-904144910
"--disable-features=CalculateNativeWinOcclusion",
"--disable-extension=vscode.vscode-api-tests"
],
"userDataDir": "${userHome}/.vscode-oss-dev",
"webRoot": "${workspaceFolder}",
"cascadeTerminateToConfigurations": [
"Attach to Extension Host"
],
"pauseForSourceMap": false,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"browserLaunchLocation": "workspace",
"presentation": {
"hidden": true,
},
},
{
"type": "node",
"request": "launch",
"name": "VS Code Server (Web)",
"runtimeExecutable": "${workspaceFolder}/scripts/code-server.sh",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/code-server.bat",
},
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "0_vscode",
"order": 2
}
},
{
"type": "node",
"request": "launch",
"name": "Main Process",
"attachSimplePort": 5875,
"enableContentValidation": false,
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.bat",
},
"runtimeArgs": [
"--inspect-brk=5875",
"--no-cached-data",
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "1_vscode",
"order": 1
}
},
{
"type": "chrome",
"request": "launch",
"outFiles": [],
"perScriptSourcemaps": "yes",
"name": "VS Code Server (Web, Chrome)",
"url": "http://localhost:8080?tkn=dev-token",
"preLaunchTask": "Run code server",
"presentation": {
"group": "0_vscode",
"order": 3
}
},
{
"type": "msedge",
"request": "launch",
"outFiles": [],
"perScriptSourcemaps": "yes",
"name": "VS Code Server (Web, Edge)",
"url": "http://localhost:8080?tkn=dev-token",
"pauseForSourceMap": false,
"preLaunchTask": "Run code server",
"presentation": {
"group": "0_vscode",
"order": 3
}
},
{
"type": "chrome",
"request": "launch",
"outFiles": [],
"perScriptSourcemaps": "yes",
"name": "VS Code Web (Chrome)",
"url": "http://localhost:8080",
"preLaunchTask": "Run code web",
"presentation": {
"group": "0_vscode",
"order": 3
}
},
{
"type": "msedge",
"request": "launch",
"outFiles": [],
"perScriptSourcemaps": "yes",
"name": "VS Code Web (Edge)",
"url": "http://localhost:8080",
"pauseForSourceMap": false,
"preLaunchTask": "Run code web",
"presentation": {
"group": "0_vscode",
"order": 3
}
},
{
"type": "node",
"request": "launch",
"name": "Git Unit Tests",
"program": "${workspaceFolder}/extensions/git/node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"cwd": "${workspaceFolder}/extensions/git",
"outFiles": [
"${workspaceFolder}/extensions/git/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 10
}
},
{
"type": "node",
"request": "launch",
"name": "HTML Server Unit Tests",
"program": "${workspaceFolder}/extensions/html-language-features/server/test/index.js",
"stopOnEntry": false,
"cwd": "${workspaceFolder}/extensions/html-language-features/server",
"outFiles": [
"${workspaceFolder}/extensions/html-language-features/server/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 10
}
},
{
"type": "node",
"request": "launch",
"name": "CSS Server Unit Tests",
"program": "${workspaceFolder}/extensions/css-language-features/server/test/index.js",
"stopOnEntry": false,
"cwd": "${workspaceFolder}/extensions/css-language-features/server",
"outFiles": [
"${workspaceFolder}/extensions/css-language-features/server/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 10
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "Markdown Extension Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/markdown-language-features/test-workspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/markdown-language-features",
"--extensionTestsPath=${workspaceFolder}/extensions/markdown-language-features/out/test"
],
"outFiles": [
"${workspaceFolder}/extensions/markdown-language-features/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 7
}
},
{
"type": "extensionHost",
"request": "launch",
"name": "TypeScript Extension Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/typescript-language-features/test-workspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/typescript-language-features",
"--extensionTestsPath=${workspaceFolder}/extensions/typescript-language-features/out/test"
],
"outFiles": [
"${workspaceFolder}/extensions/typescript-language-features/out/**/*.js"
],
"presentation": {
"group": "5_tests",
"order": 8
}
},
{
"type": "node",
"request": "launch",
"name": "Run Unit Tests",
"program": "${workspaceFolder}/test/unit/electron/index.js",
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.exe"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/code-oss"
},
"outputCapture": "std",
"args": [
"--remote-debugging-port=9222"
],
"cwd": "${workspaceFolder}",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"cascadeTerminateToConfigurations": [
"Attach to VS Code"
],
"env": {
"MOCHA_COLORS": "true"
},
"presentation": {
"hidden": true
}
},
{
"type": "node",
"request": "launch",
"name": "Run Unit Tests For Current File",
"program": "${workspaceFolder}/test/unit/electron/index.js",
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.exe"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/code-oss"
},
"cascadeTerminateToConfigurations": [
"Attach to VS Code"
],
"outputCapture": "std",
"args": [
"--remote-debugging-port=9222",
"--run",
"${relativeFile}"
],
"cwd": "${workspaceFolder}",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"env": {
"MOCHA_COLORS": "true"
},
"presentation": {
"hidden": true
}
},
{
"type": "node",
"request": "launch",
"name": "Launch Smoke Test",
"program": "${workspaceFolder}/test/smoke/test/index.js",
"cwd": "${workspaceFolder}/test/smoke",
"timeout": 240000,
"args": [
"-l",
"${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron"
],
"outFiles": [
"${cwd}/out/**/*.js"
],
"env": {
"NODE_ENV": "development",
"VSCODE_DEV": "1",
"VSCODE_CLI": "1"
}
},
{
"name": "Launch Built-in Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch"
]
},
{
"name": "Monaco Editor Playground",
"type": "chrome",
"request": "launch",
"url": "http://localhost:5001",
"preLaunchTask": "Launch Http Server",
"presentation": {
"group": "monaco",
"order": 4
}
}
],
"compounds": [
{
"name": "VS Code",
"stopAll": true,
"configurations": [
"Launch VS Code Internal",
"Attach to Main Process",
"Attach to Extension Host",
"Attach to Shared Process",
],
"preLaunchTask": "Ensure Prelaunch Dependencies",
"presentation": {
"group": "0_vscode",
"order": 1
}
},
{
"name": "VS Code (Debug Observables)",
"stopAll": true,
"configurations": [
"Launch VS Code Internal (Dev Debug)",
"Attach to Main Process",
"Attach to Extension Host",
"Attach to Shared Process",
],
"preLaunchTask": "Ensure Prelaunch Dependencies",
"presentation": {
"group": "0_vscode",
"order": 1
}
},
{
"name": "Search, Renderer, and Main processes",
"configurations": [
"Launch VS Code Internal",
"Attach to Main Process",
"Attach to Search Process"
],
"presentation": {
"group": "1_vscode",
"order": 4
}
},
{
"name": "Renderer, Extension Host, and Main processes",
"configurations": [
"Launch VS Code Internal",
"Attach to Main Process",
"Attach to Extension Host"
],
"presentation": {
"group": "1_vscode",
"order": 3
}
},
{
"name": "Debug Unit Tests",
"configurations": [
"Attach to VS Code",
"Run Unit Tests"
],
"presentation": {
"group": "1_vscode",
"order": 2
}
},
{
"name": "Debug Unit Tests (Current File)",
"configurations": [
"Attach to VS Code",
"Run Unit Tests For Current File"
],
"presentation": {
"group": "1_vscode",
"order": 2
}
},
{
"name": "Renderer and Main processes",
"stopAll": true,
"configurations": [
"Launch VS Code Internal",
"Attach to Main Process"
],
"preLaunchTask": "Ensure Prelaunch Dependencies"
},
]
}
================================================
FILE: .vscode/notebooks/api.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "#### Config"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"March 2025\""
},
{
"kind": 1,
"language": "markdown",
"value": "### Finalization"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPO $MILESTONE label:api-finalization"
},
{
"kind": 1,
"language": "markdown",
"value": "### Proposals"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPO $MILESTONE is:open label:api-proposal sort:created-asc"
}
]
================================================
FILE: .vscode/notebooks/endgame.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "#### Macros"
},
{
"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\r\n\r\n$MILESTONE=milestone:\"March 2025\""
},
{
"kind": 1,
"language": "markdown",
"value": "# Preparation"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Pull Requests on the Milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:pr is:open"
},
{
"kind": 1,
"language": "markdown",
"value": "## Unverified Older Insiders-Released Issues"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS -$MILESTONE is:issue is:closed reason:completed label:bug label:insiders-released -label:verified -label:*duplicate -label:*as-designed -label:z-author-verified -label:on-testplan -label:error-telemetry"
},
{
"kind": 1,
"language": "markdown",
"value": "## Unverified Older Insiders-Released Feature Requests"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS -$MILESTONE is:issue is:closed reason:completed label:feature-request label:insiders-released -label:on-testplan -label:verified -label:*duplicate -label:error-telemetry"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Issues on the Milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:open -label:iteration-plan -label:endgame-plan -label:testplan-item"
},
{
"kind": 1,
"language": "markdown",
"value": "## Feature Requests Missing Labels"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed label:feature-request -label:verification-needed -label:on-testplan -label:verified -label:*duplicate"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Test Plan Items without milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:open label:testplan-item no:milestone"
},
{
"kind": 1,
"language": "markdown",
"value": "# Testing"
},
{
"kind": 1,
"language": "markdown",
"value": "## Test Plan Items"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS is:issue is:open label:testplan-item"
},
{
"kind": 1,
"language": "markdown",
"value": "## Verification Needed"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed label:verification-needed -label:verified -label:on-testplan"
},
{
"kind": 1,
"language": "markdown",
"value": "# Verification"
},
{
"kind": 1,
"language": "markdown",
"value": "## Verifiable Fixes"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:z-author-verified -label:unreleased -label:*not-reproducible -label:*out-of-scope"
},
{
"kind": 1,
"language": "markdown",
"value": "## Verifiable Fixes Missing Steps"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug label:verification-steps-needed -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:z-author-verified -label:unreleased -label:*not-reproducible"
},
{
"kind": 1,
"language": "markdown",
"value": "## Unreleased Fixes"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:z-author-verified label:unreleased -label:*not-reproducible"
},
{
"kind": 1,
"language": "markdown",
"value": "## All Unverified Fixes"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:z-author-verified -label:*not-reproducible"
},
{
"kind": 1,
"language": "markdown",
"value": "# Candidates"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE is:issue is:open label:candidate"
}
]
================================================
FILE: .vscode/notebooks/grooming-delta.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "## Config"
},
{
"kind": 2,
"language": "github-issues",
"value": "$since=2021-10-01"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode\n\nQuery exceeds the maximum result. Run the query manually: `is:issue is:open closed:>2021-10-01`"
},
{
"kind": 2,
"language": "github-issues",
"value": "//repo:microsoft/vscode is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "//repo:microsoft/vscode is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-remote-release"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-remote-release is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-remote-release is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-editor"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-editor is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-editor is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-docs"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-docs is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-docs is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-js-debug"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-js-debug is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-js-debug is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# language-server-protocol"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/language-server-protocol is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/language-server-protocol is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-eslint"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-eslint is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-eslint is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-css-languageservice"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-css-languageservice is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-css-languageservice is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-test"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-test is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-test is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-pull-request-github"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-pull-request-github is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-test is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-chrome-debug-core"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-chrome-debug-core is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-chrome-debug-core is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-debugadapter-node"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-debugadapter-node is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-debugadapter-node is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-emmet-helper"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-emmet-helper is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-emmet-helper is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-extension-vscode\n\nDeprecated"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-extension-vscode is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-extension-vscode is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-extension-samples"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-extension-samples is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-extension-samples is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-filewatcher-windows"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-filewatcher-windows is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-filewatcher-windows is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-generator-code"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-generator-code is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-generator-code is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-html-languageservice"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-html-languageservice is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-html-languageservice is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-json-languageservice"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-json-languageservice is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-json-languageservice is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-languageserver-node"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-languageserver-node is:issue closed:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": ""
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-languageserver-node is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-loader"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-loader is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-loader is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-mono-debug"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-mono-debug is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-mono-debug is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-node-debug"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-node-debug is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-node-debug is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-node-debug2"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-node-debug2 is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-node-debug2 is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-recipes"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-recipes is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-recipes is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-textmate"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-textmate is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-textmate is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-themes"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-themes is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-themes is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-vsce"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-vsce is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-vsce is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-website"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-website is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-website is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-windows-process-tree"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-windows-process-tree is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-windows-process-tree is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# debug-adapter-protocol"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/debug-adapter-protocol is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/debug-adapter-protocol is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# inno-updater"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/inno-updater is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/inno-updater is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-languages"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-languages is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-languages is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-typescript"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-typescript is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-typescript is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-css"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-css is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-css is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-json"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-json is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-json is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-html"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-html is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-html is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# monaco-editor-webpack-plugin"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-editor-webpack-plugin is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/monaco-editor-webpack-plugin is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# node-jsonc-parser"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/node-jsonc-parser is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/node-jsonc-parser is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-jupyter"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-jupyter is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-jupyter is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-python"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-python is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-python is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-livepreview"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-livepreview is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-livepreview is:issue created:>$since"
},
{
"kind": 1,
"language": "markdown",
"value": ""
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode-test"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-test is:issue closed:>$since"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-test is:issue created:>$since"
}
]
================================================
FILE: .vscode/notebooks/grooming.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "#### Config"
},
{
"kind": 2,
"language": "github-issues",
"value": "// list of repos we work in\r\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\r\n\r\n$assignee=@me\r\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Missing Type label\r\n"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos assignee:$assignee is:open type:issue -label:bug -label:\"info-needed\" -label:feature-request -label:under-discussion -label:debt -label:plan-item -label:upstream -label:polish -label:testplan-item -label:error-telemetry -label:engineering -label:endgame-plan\r\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Missing Area Label\r\n\r\nFeature area labels are light or strong blue (`1d76db` or `c5def5`) and they denote a specific feature or feature area, like `editor-clipboard` or `file-explorer`\r\n"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode assignee:$assignee is:open type:issue -label:\"info-needed\" -label:api -label:api-finalization -label:api-proposal -label:authentication -label:bisect-ext -label:bracket-pair-colorization -label:bracket-pair-guides -label:breadcrumbs -label:callhierarchy -label:chrome-devtools -label:cloud-changes -label:code-lens -label:command-center -label:comments -label:config -label:containers -label:context-keys -label:continue-working-on -label:css-less-scss -label:custom-editors -label:debug -label:debug-disassembly -label:dialogs -label:diff-editor -label:dropdown -label:editor-api -label:editor-autoclosing -label:editor-autoindent -label:editor-bracket-matching -label:editor-clipboard -label:editor-code-actions -label:editor-color-picker -label:editor-columnselect -label:editor-commands -label:editor-comments -label:editor-contrib -label:editor-core -label:editor-drag-and-drop -label:editor-error-widget -label:editor-find -label:editor-folding -label:editor-highlight -label:editor-hover -label:editor-indent-detection -label:editor-indent-guides -label:editor-input -label:editor-input-IME -label:editor-insets -label:editor-minimap -label:editor-multicursor -label:editor-parameter-hints -label:editor-render-whitespace -label:editor-rendering -label:editor-widgets -label:editor-RTL -label:editor-scrollbar -label:editor-sorting -label:editor-sticky-scroll -label:editor-symbols -label:editor-synced-region -label:editor-textbuffer -label:editor-theming -label:editor-wordnav -label:editor-wrapping -label:emmet -label:emmet-parse -label:error-list -label:extension-activation -label:extension-host -label:extension-prerelease -label:extension-recommendations -label:extensions -label:extensions-development -label:file-decorations -label:file-encoding -label:file-explorer -label:file-glob -label:file-io -label:file-nesting -label:file-watcher -label:font-rendering -label:formatting -label:getting-started -label:ghost-text -label:git -label:github -label:github-repositories -label:gpu -label:grammar -label:grid-widget -label:html -label:icon-brand -label:icons-product -label:image-preview -label:inlay-hints -label:inline-completions -label:install-update -label:intellisense-config -label:interactive-playground -label:interactive-window -label:issue-bot -label:issue-reporter -label:javascript -label:json -label:keybindings -label:keybindings-editor -label:keyboard-layout -label:chat -label:l10n-platform -label:label-provider -label:languages-basic -label:languages-diagnostics -label:languages-guessing -label:layout -label:lcd-text-rendering -label:list-widget -label:live-preview -label:log -label:markdown -label:marketplace -label:menus -label:merge-conflict -label:merge-editor -label:merge-editor-workbench -label:monaco-editor -label:native-file-dialog -label:network -label:notebook -label:notebook-accessibility -label:notebook-api -label:notebook-cell-editor -label:notebook-celltoolbar -label:notebook-clipboard -label:notebook-commands -label:notebook-debugging -label:notebook-diff -label:notebook-dnd -label:notebook-execution -label:notebook-find -label:notebook-folding -label:notebook-getting-started -label:notebook-globaltoolbar -label:notebook-ipynb -label:notebook-kernel -label:notebook-kernel-picker -label:notebook-language -label:notebook-layout -label:notebook-markdown -label:notebook-output -label:notebook-perf -label:notebook-remote -label:notebook-serialization -label:notebook-statusbar -label:notebook-toc-outline -label:notebook-undo-redo -label:notebook-variables -label:notebook-workbench-integration -label:notebook-workflow -label:notebook-sticky-scroll -label:notebook-format -label:notebook-code-actions -label:open-editors -label:opener -label:outline -label:output -label:packaging -label:perf -label:perf-bloat -label:perf-startup -label:php -label:portable-mode -label:proxy -label:quick-open -label:quick-pick -label:references-viewlet -label:release-notes -label:remote -label:remote-connection -label:remote-explorer -label:remote-tunnel -label:rename -label:runCommands -label:sandbox -label:sash-widget -label:scm -label:screencast-mode -label:search -label:search-api -label:search-editor -label:search-replace -label:semantic-tokens -label:server -label:settings-editor -label:settings-sync -label:settings-sync-server -label:shared-process -label:simple-file-dialog -label:smart-select -label:snap -label:snippets -label:splitview-widget -label:ssh -label:suggest -label:table-widget -label:tasks -label:telemetry -label:terminal -label:terminal-accessibility -label:terminal-conpty -label:terminal-editors -label:terminal-external -label:terminal-find -label:terminal-input -label:terminal-layout -label:terminal-links -label:terminal-local-echo -label:terminal-persistence -label:terminal-process -label:terminal-profiles -label:terminal-quick-fix -label:terminal-rendering -label:terminal-shell-bash -label:terminal-shell-cmd -label:terminal-shell-fish -label:terminal-shell-git-bash -label:terminal-shell-integration -label:terminal-shell-pwsh -label:terminal-shell-zsh -label:terminal-sticky-scroll -label:terminal-tabs -label:testing -label:themes -label:timeline -label:timeline-git -label:timeline-local-history -label:titlebar -label:tokenization -label:touch/pointer -label:trackpad/scroll -label:tree-views -label:tree-widget -label:typescript -label:undo-redo -label:unicode-highlight -label:uri -label:user-profiles -label:ux -label:variable-resolving -label:VIM -label:virtual-workspaces -label:vscode-website -label:vscode.dev -label:web -label:webview -label:webview-views -label:workbench-actions -label:workbench-banner -label:workbench-cli -label:workbench-diagnostics -label:workbench-dnd -label:workbench-editor-grid -label:workbench-editor-groups -label:workbench-editor-resolver -label:workbench-editors -label:workbench-electron -label:workbench-fonts -label:workbench-history -label:workbench-hot-exit -label:workbench-hover -label:workbench-launch -label:workbench-link -label:workbench-multiroot -label:workbench-notifications -label:workbench-os-integration -label:workbench-rapid-render -label:workbench-run-as-admin -label:workbench-state -label:workbench-status -label:workbench-tabs -label:workbench-touchbar -label:workbench-untitled-editors -label:workbench-views -label:workbench-welcome -label:workbench-window -label:workbench-workspace -label:workbench-zen -label:workspace-edit -label:workspace-symbols -label:workspace-trust -label:zoom -label:inline-chat -label:panel-chat -label:quick-chat -label:tasks -label:error-list -label:winget -label:tree-views -label:freeze-slow-crash-leak -label:engineering -label:cross-file-editing -label:microsoft-authentication -label:github-authentication -label:lm-access -label:secret-storage"
},
{
"kind": 1,
"language": "markdown",
"value": "### Missing Milestone\r\n"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos assignee:$assignee is:open type:issue no:milestone -label:info-needed -label:triage-needed -label:confirmation-pending -label:under-discussion\r\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Not Actionable\r\n"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos assignee:$assignee is:open label:\"info-needed\"\r\n"
}
]
================================================
FILE: .vscode/notebooks/inbox.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "## tl;dr: Triage Inbox\n\nAll inbox issues but not those that need more information. These issues need to be triaged, e.g assigned to a user or ask for more information"
},
{
"kind": 2,
"language": "github-issues",
"value": "$inbox -label:\"info-needed\" sort:created-desc"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode label:triage-needed is:open"
},
{
"kind": 1,
"language": "markdown",
"value": "##### `Config`: defines the inbox query"
},
{
"kind": 2,
"language": "github-issues",
"value": "$inbox=repo:microsoft/vscode is:open no:assignee -label:feature-request -label:testplan-item -label:plan-item "
},
{
"kind": 1,
"language": "markdown",
"value": "## Inbox tracking and Issue triage"
},
{
"kind": 1,
"language": "markdown",
"value": "New issues or pull requests submitted by the community are initially triaged by an [automatic classification bot](https://github.com/microsoft/vscode-github-triage-actions/tree/master/classifier-deep). Issues that the bot does not correctly triage are then triaged by a team member. The team rotates the inbox tracker on a weekly basis.\n\nA [mirror](https://github.com/JacksonKearl/testissues/issues) of the VS Code issue stream is available with details about how the bot classifies issues, including feature-area classifications and confidence ratings. Per-category confidence thresholds and feature-area ownership data is maintained in [.github/classifier.json](https://github.com/microsoft/vscode/blob/main/.github/classifier.json). \n\n💡 The bot is being run through a GitHub action that runs every 30 minutes. Give the bot the opportunity to classify an issue before doing it manually.\n\n### Inbox Tracking\n\nThe inbox tracker is responsible for the [global inbox](https://github.com/microsoft/vscode/issues?utf8=%E2%9C%93&q=is%3Aopen+no%3Aassignee+-label%3Afeature-request+-label%3Atestplan-item+-label%3Aplan-item) containing all **open issues and pull requests** that\n- are neither **feature requests** nor **test plan items** nor **plan items** and\n- have **no owner assignment**.\n\nThe **inbox tracker** may perform any step described in our [issue triaging documentation](https://github.com/microsoft/vscode/wiki/Issues-Triaging) but its main responsibility is to route issues to the actual feature area owner.\n\nFeature area owners track the **feature area inbox** containing all **open issues and pull requests** that\n- are personally assigned to them and are not assigned to any milestone\n- are labeled with their feature area label and are not assigned to any milestone.\nThis secondary triage may involve any of the steps described in our [issue triaging documentation](https://github.com/microsoft/vscode/wiki/Issues-Triaging) and results in a fully triaged or closed issue.\n\nThe [github triage extension](https://github.com/microsoft/vscode-github-triage-extension) can be used to assist with triaging — it provides a \"Command Palette\"-style list of triaging actions like assignment, labeling, and triggers for various bot actions."
},
{
"kind": 1,
"language": "markdown",
"value": "## All Inbox Items\n\nAll issues that have no assignee and that have neither **feature requests** nor **test plan items** nor **plan items**."
},
{
"kind": 2,
"language": "github-issues",
"value": "$inbox"
}
]
================================================
FILE: .vscode/notebooks/my-endgame.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "#### Macros"
},
{
"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\n$MILESTONE=milestone:\"March 2025\"\n\n$MINE=assignee:@me"
},
{
"kind": 1,
"language": "markdown",
"value": "# Preparation"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Pull Requests on the Milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:pr is:open"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Issues on the Milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue is:open -label:iteration-plan -label:endgame-plan -label:testplan-item"
},
{
"kind": 1,
"language": "markdown",
"value": "## Feature Requests Missing Labels"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request -label:verification-needed -label:on-testplan -label:verified -label:*duplicate"
},
{
"kind": 1,
"language": "markdown",
"value": "## Test Plan Items"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS is:issue is:open author:@me label:testplan-item"
},
{
"kind": 1,
"language": "markdown",
"value": "## Verification Needed"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request label:verification-needed -label:verified -label:on-testplan"
},
{
"kind": 1,
"language": "markdown",
"value": "# Testing"
},
{
"kind": 1,
"language": "markdown",
"value": "## Test Plan Items"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MINE is:issue is:open label:testplan-item"
},
{
"kind": 1,
"language": "markdown",
"value": "## Verification Needed"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed -assignee:@me -label:verified -label:z-author-verified label:feature-request label:verification-needed -label:verification-steps-needed -label:unreleased -label:on-testplan"
},
{
"kind": 1,
"language": "markdown",
"value": "# Fixing"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Issues"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue is:open -label:endgame-plan -label:testplan-item -label:iteration-plan"
},
{
"kind": 1,
"language": "markdown",
"value": "## Open Bugs"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue is:open label:bug"
},
{
"kind": 1,
"language": "markdown",
"value": "# Verification"
},
{
"kind": 1,
"language": "markdown",
"value": "## My Issues (verification-steps-needed)"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue label:bug label:verification-steps-needed"
},
{
"kind": 1,
"language": "markdown",
"value": "## My Issues (verification-found)"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue label:bug label:verification-found"
},
{
"kind": 1,
"language": "markdown",
"value": "## Issues filed by me"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed author:@me sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:triage-needed -label:verification-found -label:*not-reproducible"
},
{
"kind": 1,
"language": "markdown",
"value": "## Issues filed from outside team"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:*out-of-scope -label:error-telemetry -label:verification-steps-needed -label:verification-found -author:aeschli -author:alexdima -author:alexr00 -author:AmandaSilver -author:andreamah -author:bamurtaugh -author:bpasero -author:chrisdias -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:joyceerhl -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:tanhakabir -author:TylerLeonhardt -author:Tyriar -author:weinand -author:amunger -author:karthiknadig -author:eleanorjboyd -author:Yoyokrazy -author:paulacamargo25 -author:ulugbekna -author:aiday-mar -author:daviddossett -author:bhavyaus -author:justschen -author:benibenj -author:luabud -author:anthonykim1 -author:joshspicer -author:osortega -author:legomushroom"
},
{
"kind": 1,
"language": "markdown",
"value": "## Issues filed by others"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed -author:@me sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:verification-found -label:*not-reproducible -label:*out-of-scope"
},
{
"kind": 1,
"language": "markdown",
"value": "## Test steps needed from others"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE -$MINE is:issue label:bug label:verification-steps-needed -label:verified"
},
{
"kind": 1,
"language": "markdown",
"value": "# Release Notes"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request -label:on-release-notes\r\n$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:engineering -label:on-release-notes\r\n$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:plan-item -label:on-release-notes"
}
]
================================================
FILE: .vscode/notebooks/my-work.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "##### `Config`: This should be changed every month/milestone"
},
{
"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:\"March 2025\"\n"
},
{
"kind": 1,
"language": "markdown",
"value": "## Milestone Work"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS $MILESTONE assignee:@me is:open\n"
},
{
"kind": 1,
"language": "markdown",
"value": "## Bugs, Debt, Features..."
},
{
"kind": 1,
"language": "markdown",
"value": "#### My Bugs"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open label:bug\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Debt & Engineering"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open label:debt,engineering\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Performance 🐌 🔜 🏎"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open label:perf,perf-startup,perf-bloat,freeze-slow-crash-leak\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Feature Requests"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open label:feature-request milestone:Backlog sort:reactions-+1-desc\n"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open milestone:\"Backlog Candidates\"\n"
},
{
"kind": 1,
"language": "markdown",
"value": "### Personal Inbox"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Triage Needed"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS is:open assignee:@me label:triage-needed\n"
},
{
"kind": 1,
"language": "markdown",
"value": "\n#### Missing Type label"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open type:issue -label:bug -label:\"info-needed\" -label:feature-request -label:under-discussion -label:debt -label:plan-item -label:upstream -label:polish -label:testplan-item -label:error-telemetry -label:engineering\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Missing Area Label\n\nFeature area labels are light or strong blue (`1d76db` or `c5def5`) and they denote a specific feature or feature area, like `editor-clipboard` or `file-explorer`"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode assignee:@me is:open type:issue -label:\"info-needed\" -label:api -label:api-finalization -label:api-proposal -label:authentication -label:bisect-ext -label:bracket-pair-colorization -label:bracket-pair-guides -label:breadcrumbs -label:callhierarchy -label:chrome-devtools -label:code-lens -label:command-center -label:comments -label:config -label:context-keys -label:custom-editors -label:debug -label:debug-console -label:debug-disassembly -label:dialogs -label:diff-editor -label:dropdown -label:editor-api -label:editor-autoclosing -label:editor-autoindent -label:editor-bracket-matching -label:editor-clipboard -label:editor-code-actions -label:editor-color-picker -label:editor-columnselect -label:editor-commands -label:editor-comments -label:editor-contrib -label:editor-core -label:editor-drag-and-drop -label:editor-error-widget -label:editor-find -label:editor-folding -label:editor-highlight -label:editor-hover -label:editor-indent-detection -label:editor-indent-guides -label:editor-input -label:editor-input-IME -label:editor-insets -label:editor-minimap -label:editor-multicursor -label:editor-parameter-hints -label:editor-render-whitespace -label:editor-rendering -label:editor-RTL -label:editor-scrollbar -label:editor-sorting -label:editor-sticky-scroll -label:editor-sticky-scroll-decorations -label:editor-symbols -label:editor-synced-region -label:editor-textbuffer -label:editor-theming -label:editor-wordnav -label:editor-wrapping -label:emmet-parse -label:extension-activation -label:extension-host -label:extension-prerelease -label:extension-recommendations -label:extension-signature -label:extensions -label:extensions-development -label:file-decorations -label:file-encoding -label:file-explorer -label:file-glob -label:file-io -label:file-nesting -label:file-watcher -label:font-rendering -label:formatting -label:getting-started -label:ghost-text -label:git -label:github -label:github-repositories -label:gpu -label:grammar -label:grid-widget -label:icon-brand -label:icons-product -label:icons-widget -label:inlay-hints -label:inline-chat -label:inline-completions -label:install-update -label:intellisense-config -label:interactive-playground -label:interactive-window -label:javascript -label:json -label:json-sorting -label:keybindings -label:keybindings-editor -label:keyboard-layout -label:L10N -label:l10n-platform -label:label-provider -label:languages-basic -label:languages-diagnostics -label:languages-guessing -label:layout -label:lcd-text-rendering -label:list-widget -label:live-preview -label:log -label:markdown -label:marketplace -label:menus -label:merge-conflict -label:merge-editor -label:merge-editor-workbench -label:monaco-editor -label:multi-monitor -label:native-file-dialog -label:network -label:notebook -label:notebook-accessibility -label:notebook-api -label:notebook-cell-editor -label:notebook-celltoolbar -label:notebook-clipboard -label:notebook-code-actions -label:notebook-commands -label:notebook-debugging -label:notebook-diff -label:notebook-dnd -label:notebook-execution -label:notebook-find -label:notebook-folding -label:notebook-format -label:notebook-getting-started -label:notebook-globaltoolbar -label:notebook-ipynb -label:notebook-kernel -label:notebook-kernel-picker -label:notebook-language -label:notebook-layout -label:notebook-markdown -label:notebook-output -label:notebook-perf -label:notebook-remote -label:notebook-serialization -label:notebook-statusbar -label:notebook-sticky-scroll -label:notebook-toc-outline -label:notebook-undo-redo -label:notebook-variables -label:notebook-workbench-integration -label:notebook-workflow -label:open-editors -label:opener -label:outline -label:output -label:packaging -label:panel-chat -label:perf -label:perf-bloat -label:perf-startup -label:php -label:portable-mode -label:proxy -label:quick-open -label:quick-pick -label:quickpick-chat -label:references-viewlet -label:release-notes -label:remote -label:remote-connection -label:remote-desktop -label:remote-explorer -label:remote-tunnel -label:rename -label:runCommands -label:sandbox -label:sash-widget -label:scm -label:screencast-mode -label:search -label:search-api -label:search-editor -label:search-replace -label:semantic-tokens -label:server -label:settings-editor -label:settings-search -label:settings-sync -label:settings-sync-server -label:shared-process -label:simple-file-dialog -label:smart-select -label:snap -label:snippets -label:splitview-widget -label:ssh -label:suggest -label:system-context-menu -label:table-widget -label:tasks -label:telemetry -label:terminal -label:terminal-accessibility -label:terminal-conpty -label:terminal-editors -label:terminal-external -label:terminal-find -label:terminal-input -label:terminal-layout -label:terminal-links -label:terminal-local-echo -label:terminal-persistence -label:terminal-process -label:terminal-profiles -label:terminal-quick-fix -label:terminal-rendering -label:terminal-shell-bash -label:terminal-shell-cmd -label:terminal-shell-fish -label:terminal-shell-git-bash -label:terminal-shell-integration -label:terminal-shell-pwsh -label:terminal-shell-zsh -label:terminal-tabs -label:testing -label:themes -label:timeline -label:timeline-git -label:timeline-local-history -label:titlebar -label:tokenization -label:touch/pointer -label:trackpad/scroll -label:tree-views -label:tree-widget -label:typescript -label:unc -label:undo-redo -label:unicode-highlight -label:uri -label:user-profiles -label:ux -label:variable-resolving -label:VIM -label:virtual-documents -label:virtual-workspaces -label:vscode-website -label:vscode.dev -label:web -label:webview -label:webview-views -label:workbench-actions -label:workbench-auxwindow -label:workbench-banner -label:workbench-cli -label:workbench-diagnostics -label:workbench-dnd -label:workbench-editor-grid -label:workbench-editor-groups -label:workbench-editor-resolver -label:workbench-editors -label:workbench-electron -label:workbench-fonts -label:workbench-history -label:workbench-hot-exit -label:workbench-hover -label:workbench-launch -label:workbench-link -label:workbench-multiroot -label:workbench-notifications -label:workbench-os-integration -label:workbench-rapid-render -label:workbench-run-as-admin -label:workbench-state -label:workbench-status -label:workbench-tabs -label:workbench-touchbar -label:workbench-untitled-editors -label:workbench-views -label:workbench-voice -label:workbench-welcome -label:workbench-window -label:workbench-workspace -label:workbench-zen -label:workspace-edit -label:workspace-symbols -label:workspace-trust -label:zoom -label:error-list -label:winget -label:cross-file-editing -label:editor-refactor-preview"
},
{
"kind": 1,
"language": "markdown",
"value": "### Missing Milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open type:issue no:milestone -label:info-needed -label:triage-needed\n"
},
{
"kind": 1,
"language": "markdown",
"value": "#### Not Actionable"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS assignee:@me is:open label:\"info-needed\"\n"
},
{
"kind": 1,
"language": "markdown",
"value": "### Pull Requests"
},
{
"kind": 1,
"language": "markdown",
"value": "✅ Approved"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS author:@me is:open is:pr review:approved\n"
},
{
"kind": 1,
"language": "markdown",
"value": "⌛ Pending Approval"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS author:@me is:open is:pr review:required\n"
},
{
"kind": 1,
"language": "markdown",
"value": "⚠️ Changes Requested"
},
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS author:@me is:open is:pr review:changes_requested\n"
}
]
================================================
FILE: .vscode/notebooks/papercuts.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "## Papercuts\n\nThis notebook serves as an ongoing collection of papercut issues that we encounter while dogfooding. With that in mind only promote issues that really turn you off, e.g. issues that make you want to stop using VS Code or its extensions. To mark an issue (bug, feature-request, etc.) as papercut add the labels: `papercut :drop_of_blood:`",
"editable": true
},
{
"kind": 1,
"language": "markdown",
"value": "## All Papercuts\n\nThese are all papercut issues that we encounter while dogfooding vscode or extensions that we author.",
"editable": true
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode is:open -label:notebook label:\"papercut :drop_of_blood:\"",
"editable": true
},
{
"kind": 1,
"language": "markdown",
"value": "## Native Notebook",
"editable": true
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode is:open label:notebook label:\"papercut :drop_of_blood:\"",
"editable": true
},
{
"kind": 1,
"language": "markdown",
"value": "### My Papercuts",
"editable": true
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode is:open assignee:@me label:\"papercut :drop_of_blood:\"",
"editable": true
}
]
================================================
FILE: .vscode/notebooks/verification.github-issues
================================================
[
{
"kind": 1,
"language": "markdown",
"value": "### Bug Verification Queries\n\nBefore shipping we want to verify _all_ bugs. That means when a bug is fixed we check that the fix actually works. It's always best to start with bugs that you have filed and the proceed with bugs that have been filed from users outside the development team. "
},
{
"kind": 1,
"language": "markdown",
"value": "#### Config: update list of `repos` and the `milestone`"
},
{
"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:\"November 2023\"\n$closedRecently=closed:>2023-09-29"
},
{
"kind": 1,
"language": "markdown",
"value": "### Bugs You Filed"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos $milestone is:closed reason:completed -assignee:@me label:bug -label:verified -label:*duplicate author:@me"
},
{
"kind": 1,
"language": "markdown",
"value": "### Bugs From Outside"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos $milestone is:closed reason:completed -assignee:@me label:bug -label:verified -label:*duplicate -author:@me -assignee:@me label:bug -label:verified -author:@me -author:aeschli -author:alexdima -author:alexr00 -author:bpasero -author:chrisdias -author:chrmarti -author:connor4312 -author:dbaeumer -author:deepak1556 -author:eamodio -author:egamma -author:gregvanl -author:isidorn -author:JacksonKearl -author:joaomoreno -author:jrieken -author:lramos15 -author:lszomoru -author:meganrogge -author:misolori -author:mjbvz -author:rebornix -author:RMacfarlane -author:roblourens -author:sana-ajani -author:sandy081 -author:sbatten -author:Tyriar -author:weinand -author:rzhao271 -author:kieferrm -author:TylerLeonhardt -author:bamurtaugh -author:hediet -author:joyceerhl -author:rchiodo"
},
{
"kind": 1,
"language": "markdown",
"value": "### All"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos $milestone is:closed reason:completed -assignee:@me label:bug -label:verified -label:*duplicate"
},
{
"kind": 1,
"language": "markdown",
"value": "### Issues recently closed via PR without a milestone"
},
{
"kind": 2,
"language": "github-issues",
"value": "$repos is:closed linked:pr $closedRecently no:milestone -label:verified -label:*duplicate"
}
]
================================================
FILE: .vscode/notebooks/vscode-dev.github-issues
================================================
[
{
"kind": 2,
"language": "github-issues",
"value": "$milestone=milestone:\"August 2024\""
},
{
"kind": 1,
"language": "markdown",
"value": "# vscode.dev repo"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-dev $milestone is:open"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-dev milestone:\"Backlog\" is:open"
},
{
"kind": 1,
"language": "markdown",
"value": "# VS Code repo"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode label:vscode.dev is:open"
},
{
"kind": 1,
"language": "markdown",
"value": "# GitHub Repositories repos"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-remote-repositories-github $milestone is:open"
},
{
"kind": 2,
"language": "github-issues",
"value": "repo:microsoft/vscode-remotehub $milestone is:open"
}
]
================================================
FILE: .vscode/searches/ts36031.code-search
================================================
# Query: \\w+\\?\\.\\w+![(.[]
# Flags: RegExp
# ContextLines: 2
8 results - 4 files
src/vs/base/browser/ui/tree/asyncDataTree.ts:
241 } : () => 'treeitem',
242 isChecked: options.accessibilityProvider!.isChecked ? (e) => {
243: return !!(options.accessibilityProvider?.isChecked!(e.element as T));
244 } : undefined,
245 getAriaLabel(e) {
src/vs/platform/list/browser/listService.ts:
463
464 if (typeof options?.openOnSingleClick !== 'boolean' && options?.configurationService) {
465: this.openOnSingleClick = options?.configurationService!.getValue(openModeSettingKey) !== 'doubleClick';
466 this._register(options?.configurationService.onDidChangeConfiguration(() => {
467: this.openOnSingleClick = options?.configurationService!.getValue(openModeSettingKey) !== 'doubleClick';
468 }));
469 } else {
src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts:
1526
1527 await this._ensureActiveKernel();
1528: await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel!.uri, undefined);
1529 }
1530
1535
1536 await this._ensureActiveKernel();
1537: await this._activeKernel?.executeNotebookCell!(this._notebookViewModel!.uri, undefined);
1538 }
1539
1553
1554 await this._ensureActiveKernel();
1555: await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel!.uri, cell.handle);
1556 }
1557
1567
1568 await this._ensureActiveKernel();
1569: await this._activeKernel?.executeNotebookCell!(this._notebookViewModel!.uri, cell.handle);
1570 }
1571
src/vs/workbench/contrib/webview/electron-browser/iframeWebviewElement.ts:
89 .then(() => this._resourceRequestManager.ensureReady())
90 .then(() => {
91: this.element?.contentWindow!.postMessage({ channel, args: data }, '*');
92 });
93 }
================================================
FILE: .vscode/settings.json
================================================
{
"editor.insertSpaces": false,
"files.trimTrailingWhitespace": true,
"files.exclude": {
".git": true,
".build": true,
".profile-oss": true,
"**/.DS_Store": true,
".vscode-test": true,
"cli/target": true,
"build/**/*.js.map": true,
"build/**/*.js": {
"when": "$(basename).ts"
}
},
"files.associations": {
"cglicenses.json": "jsonc",
"*.tst": "typescript"
},
"search.exclude": {
"**/node_modules": true,
"cli/target/**": true,
".build/**": true,
"out/**": true,
"out-build/**": true,
"out-vscode/**": true,
"i18n/**": true,
"extensions/**/dist/**": true,
"extensions/**/out/**": true,
"test/smoke/out/**": true,
"test/automation/out/**": true,
"test/integration/browser/out/**": true,
"src/vs/base/test/common/filters.perf.data.js": true,
"src/vs/base/test/node/uri.perf.data.txt": true,
"src/vs/workbench/api/test/browser/extHostDocumentData.test.perf-data.ts": true,
"src/vs/base/test/node/uri.test.data.txt": true,
"src/vs/editor/test/node/diffing/fixtures/**": true,
"build/loader.min": true
},
"files.readonlyInclude": {
"**/node_modules/**/*.*": true,
"**/yarn.lock": true,
"**/package-lock.json": true,
"**/Cargo.lock": true,
"build/**/*.js": true,
"out/**": true,
"out-build/**": true,
"out-vscode/**": true,
"out-vscode-reh/**": true,
"extensions/**/dist/**": true,
"extensions/**/out/**": true,
"extensions/terminal-suggest/src/completions/upstream/**": true,
"test/smoke/out/**": true,
"test/automation/out/**": true,
"test/integration/browser/out/**": true
},
"files.readonlyExclude": {
"build/builtin/*.js": true,
"build/monaco/*.js": true,
"build/npm/*.js": true,
"build/*.js": true
},
"lcov.path": [
"./.build/coverage/lcov.info",
"./.build/coverage-single/lcov.info"
],
"lcov.watch": [
{
"pattern": "**/*.test.js",
"command": "${workspaceFolder}/scripts/test.sh --coverage --run ${file}",
"windows": {
"command": "${workspaceFolder}\\scripts\\test.bat --coverage --run ${file}"
}
}
],
"typescript.tsdk": "node_modules/typescript/lib",
"npm.exclude": "**/extensions/**",
"emmet.excludeLanguages": [],
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.quoteStyle": "single",
"json.schemas": [
{
"fileMatch": [
"cgmanifest.json"
],
"url": "https://json.schemastore.org/component-detection-manifest.json",
},
{
"fileMatch": [
"cglicenses.json"
],
"url": "./.vscode/cglicenses.schema.json"
}
],
"git.ignoreLimitWarning": true,
"git.branchProtection": [
"main",
"distro",
"release/*"
],
"git.branchProtectionPrompt": "alwaysCommitToNewBranch",
"git.branchRandomName.enable": true,
"git.pullBeforeCheckout": true,
"git.mergeEditor": true,
"remote.extensionKind": {
"msjsdiag.debugger-for-chrome": "workspace"
},
"gulp.autoDetect": "off",
"files.insertFinalNewline": true,
"[plaintext]": {
"files.insertFinalNewline": false
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.formatOnSave": true
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.formatOnSave": true
},
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true,
},
"rust-analyzer.linkedProjects": [
"cli/Cargo.toml"
],
"typescript.tsc.autoDetect": "off",
"testing.autoRun.mode": "rerun",
"conventionalCommits.scopes": [
"tree",
"scm",
"grid",
"splitview",
"table",
"list",
"git",
"sash"
],
"githubPullRequests.experimental.createView": true,
"debug.javascript.terminalOptions": {
"outFiles": [
"${workspaceFolder}/out/**/*.js",
"${workspaceFolder}/build/**/*.js"
]
},
"extension-test-runner.debugOptions": {
"outFiles": [
"${workspaceFolder}/extensions/*/out/**/*.js",
]
},
"githubPullRequests.assignCreated": "${user}",
"githubPullRequests.defaultMergeMethod": "squash",
"githubPullRequests.ignoredPullRequestBranches": [
"main"
],
"application.experimental.rendererProfiling": true,
"editor.experimental.asyncTokenization": true,
"editor.experimental.asyncTokenizationVerification": true,
"terminal.integrated.suggest.enabled": true,
"typescript.preferences.autoImportFileExcludePatterns": [
"@xterm/xterm",
"@xterm/headless",
"node-pty",
"vscode-notebook-renderer",
"src/vs/workbench/workbench.web.main.internal.ts"
],
"[github-issues]": {
"editor.wordWrap": "on"
},
"css.format.spaceAroundSelectorSeparator": true,
"typescript.enablePromptUseWorkspaceTsdk": true,
"eslint.useFlatConfig": true,
"editor.occurrencesHighlightDelay": 0,
"typescript.experimental.expandableHover": true,
"git.diagnosticsCommitHook.Enabled": true,
"git.diagnosticsCommitHook.Sources": {
"*": "error",
"ts": "warning",
"eslint": "warning"
}
}
================================================
FILE: .vscode/shared.code-snippets
================================================
{
// Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. The scope defines in watch languages the snippet is applicable. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted.Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
"MSFT Copyright Header": {
"scope": "javascript,typescript,css,rust",
"prefix": [
"header",
"stub",
"copyright"
],
"body": [
"/*---------------------------------------------------------------------------------------------",
" * Copyright (c) Microsoft Corporation. All rights reserved.",
" * Licensed under the MIT License. See License.txt in the project root for license information.",
" *--------------------------------------------------------------------------------------------*/",
"",
"$0"
],
"description": "Insert Copyright Statement"
},
"TS -> Inject Service": {
"scope": "typescript",
"description": "Constructor Injection Pattern",
"prefix": "@inject",
"body": "@$1 private readonly _$2: ${1},$0"
},
"TS -> Event & Emitter": {
"scope": "typescript",
"prefix": "emitter",
"description": "Add emitter and event properties",
"body": [
"private readonly _onDid$1 = new Emitter<$2>();",
"readonly onDid$1: Event<$2> = this._onDid$1.event;"
],
}
}
================================================
FILE: .vscode/tasks.json
================================================
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "watch-clientd",
"label": "Core - Build",
"isBackground": true,
"presentation": {
"reveal": "never",
"group": "buildWatchers",
"close": false
},
"problemMatcher": {
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": [
"absolute"
],
"pattern": {
"regexp": "Error: ([^(]+)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\): (.*)$",
"file": 1,
"location": 2,
"message": 3
},
"background": {
"beginsPattern": "Starting compilation...",
"endsPattern": "Finished compilation with"
}
}
},
{ // Void added this
"type": "npm",
"script": "watchreactd",
"label": "React - Build",
"isBackground": true,
"presentation": {
"reveal": "never",
"group": "buildWatchers",
"close": false
},
"problemMatcher": {
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": [
"absolute"
],
"pattern": {
"regexp": "Error: ([^(]+)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\): (.*)$",
"file": 1,
"location": 2,
"message": 3
},
"background": {
"beginsPattern": "Starting compilation",
"endsPattern": "Finished compilation"
}
}
},
{
"type": "npm",
"script": "watch-extensionsd",
"label": "Ext - Build",
"isBackground": true,
"presentation": {
"reveal": "never",
"group": "buildWatchers",
"close": false
},
"problemMatcher": {
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": [
"absolute"
],
"pattern": {
"regexp": "Error: ([^(]+)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\): (.*)$",
"file": 1,
"location": 2,
"message": 3
},
"background": {
"beginsPattern": "Starting compilation",
"endsPattern": "Finished compilation"
}
}
},
{
"label": "VS Code - Build",
"dependsOn": [
"Core - Build",
"React - Build",
"Ext - Build"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
},
{
"type": "npm",
"script": "kill-watch-clientd",
"label": "Kill Core - Build",
"group": "build",
"presentation": {
"reveal": "never",
"group": "buildKillers",
"close": true
},
"problemMatcher": "$tsc"
},
{
"type": "npm",
"script": "kill-watch-extensionsd",
"label": "Kill Ext - Build",
"group": "build",
"presentation": {
"reveal": "never",
"group": "buildKillers",
"close": true
},
"problemMatcher": "$tsc"
},
{
"label": "Kill VS Code - Build",
"dependsOn": [
"Kill Core - Build",
"Kill Ext - Build"
],
"group": "build",
"problemMatcher": []
},
{
"label": "Restart VS Code - Build",
"dependsOn": [
"Kill VS Code - Build",
"VS Code - Build"
],
"group": "build",
"dependsOrder": "sequence",
"problemMatcher": []
},
{
"label": "Kill VS Code - Build, Npm, VS Code - Build",
"dependsOn": [
"Kill VS Code - Build",
"npm: install",
"VS Code - Build"
],
"group": "build",
"dependsOrder": "sequence",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch-webd",
"label": "Web Ext - Build",
"group": "build",
"isBackground": true,
"presentation": {
"reveal": "never"
},
"problemMatcher": {
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": [
"absolute"
],
"pattern": {
"regexp": "Error: ([^(]+)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\): (.*)$",
"file": 1,
"location": 2,
"message": 3
},
"background": {
"beginsPattern": "Starting compilation",
"endsPattern": "Finished compilation"
}
}
},
{
"type": "npm",
"script": "kill-watch-webd",
"label": "Kill Web Ext - Build",
"group": "build",
"presentation": {
"reveal": "never"
},
"problemMatcher": "$tsc"
},
{
"label": "Run tests",
"type": "shell",
"command": "./scripts/test.sh",
"windows": {
"command": ".\\scripts\\test.bat"
},
"group": "test",
"presentation": {
"echo": true,
"reveal": "always"
}
},
{
"label": "Run Dev",
"type": "shell",
"command": "./scripts/code.sh",
"windows": {
"command": ".\\scripts\\code.bat"
},
"problemMatcher": []
},
{
"type": "npm",
"script": "electron",
"label": "Download electron"
},
{
"type": "gulp",
"task": "hygiene",
"problemMatcher": []
},
{
"type": "shell",
"command": "./scripts/code-server.sh",
"windows": {
"command": ".\\scripts\\code-server.bat"
},
"args": ["--no-launch", "--connection-token", "dev-token", "--port", "8080"],
"label": "Run code server",
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"beginsPattern": ".*node .*",
"endsPattern": "Web UI available at .*"
}
},
"presentation": {
"reveal": "never"
}
},
{
"type": "shell",
"command": "./scripts/code-web.sh",
"windows": {
"command": ".\\scripts\\code-web.bat"
},
"args": ["--port", "8080", "--browser", "none"],
"label": "Run code web",
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"beginsPattern": ".*node .*",
"endsPattern": "Listening on .*"
}
},
"presentation": {
"reveal": "never"
}
},
{
"type": "npm",
"script": "eslint",
"problemMatcher": {
"source": "eslint",
"base": "$eslint-stylish"
}
},
{
"type": "shell",
"command": "node build/lib/preLaunch.js",
"label": "Ensure Prelaunch Dependencies",
"presentation": {
"reveal": "silent",
"close": true
}
},
{
"type": "npm",
"script": "tsec-compile-check",
"problemMatcher": [
{
"base": "$tsc",
"applyTo": "allDocuments",
"owner": "tsec"
}
],
"group": "build",
"label": "npm: tsec-compile-check",
"detail": "node_modules/tsec/bin/tsec -p src/tsconfig.json --noEmit"
},
{
// Used for monaco editor playground launch config
"label": "Launch Http Server",
"type": "shell",
"command": "node_modules/.bin/ts-node -T ./scripts/playground-server",
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"activeOnStart": true,
"beginsPattern": "never match",
"endsPattern": ".*"
}
},
"dependsOn": [
"Core - Build"
]
}
]
}
================================================
FILE: .vscode-test.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 { createRequire } from 'node:module';
import { fileURLToPath } from 'url';
import * as path from 'path';
import * as os from 'os';
const require = createRequire(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { defineConfig } = require('@vscode/test-cli');
/**
* A list of extension folders who have opted into tests, or configuration objects.
* Edit me to add more!
*
* @type {Array & { label: string }>}
*/
const extensions = [
{
label: 'markdown-language-features',
workspaceFolder: `extensions/markdown-language-features/test-workspace`,
mocha: { timeout: 60_000 }
},
{
label: 'ipynb',
workspaceFolder: path.join(os.tmpdir(), `ipynb-${Math.floor(Math.random() * 100000)}`),
mocha: { timeout: 60_000 }
},
{
label: 'notebook-renderers',
workspaceFolder: path.join(os.tmpdir(), `nbout-${Math.floor(Math.random() * 100000)}`),
mocha: { timeout: 60_000 }
},
{
label: 'vscode-colorize-tests',
workspaceFolder: `extensions/vscode-colorize-tests/test`,
mocha: { timeout: 60_000 }
},
{
label: 'terminal-suggest',
workspaceFolder: path.join(os.tmpdir(), `terminal-suggest-${Math.floor(Math.random() * 100000)}`),
mocha: { timeout: 60_000 }
},
{
label: 'vscode-colorize-perf-tests',
workspaceFolder: `extensions/vscode-colorize-perf-tests/test`,
mocha: { timeout: 6000_000 }
},
{
label: 'configuration-editing',
workspaceFolder: path.join(os.tmpdir(), `confeditout-${Math.floor(Math.random() * 100000)}`),
mocha: { timeout: 60_000 }
},
{
label: 'github-authentication',
workspaceFolder: path.join(os.tmpdir(), `msft-auth-${Math.floor(Math.random() * 100000)}`),
mocha: { timeout: 60_000 }
},
{
label: 'microsoft-authentication',
mocha: { timeout: 60_000 }
},
{
label: 'vscode-api-tests-folder',
extensionDevelopmentPath: `extensions/vscode-api-tests`,
workspaceFolder: `extensions/vscode-api-tests/testWorkspace`,
mocha: { timeout: 60_000 },
files: 'extensions/vscode-api-tests/out/singlefolder-tests/**/*.test.js',
},
{
label: 'vscode-api-tests-workspace',
extensionDevelopmentPath: `extensions/vscode-api-tests`,
workspaceFolder: `extensions/vscode-api-tests/testworkspace.code-workspace`,
mocha: { timeout: 60_000 },
files: 'extensions/vscode-api-tests/out/workspace-tests/**/*.test.js',
}
];
const defaultLaunchArgs = process.env.API_TESTS_EXTRA_ARGS?.split(' ') || [
'--disable-telemetry', '--skip-welcome', '--skip-release-notes', `--crash-reporter-directory=${__dirname}/.build/crashes`, `--logsPath=${__dirname}/.build/logs/integration-tests`, '--no-cached-data', '--disable-updates', '--use-inmemory-secretstorage', '--disable-extensions', '--disable-workspace-trust'
];
const config = defineConfig(extensions.map(extension => {
/** @type {import('@vscode/test-cli').TestConfiguration} */
const config = {
platform: 'desktop',
files: `extensions/${extension.label}/out/**/*.test.js`,
extensionDevelopmentPath: `extensions/${extension.label}`,
...extension,
};
config.mocha ??= {};
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
let suite = '';
if (process.env.VSCODE_BROWSER) {
suite = `${process.env.VSCODE_BROWSER} Browser Integration ${config.label} tests`;
} else if (process.env.REMOTE_VSCODE) {
suite = `Remote Integration ${config.label} tests`;
} else {
suite = `Integration ${config.label} tests`;
}
config.mocha.reporter = 'mocha-multi-reporters';
config.mocha.reporterOptions = {
reporterEnabled: 'spec, mocha-junit-reporter',
mochaJunitReporterReporterOptions: {
testsuitesTitle: `${suite} ${process.platform}`,
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${process.arch}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
}
};
}
if (!config.platform || config.platform === 'desktop') {
config.launchArgs = defaultLaunchArgs;
config.useInstallation = {
fromPath: process.env.INTEGRATION_TEST_ELECTRON_PATH || `${__dirname}/scripts/code.${process.platform === 'win32' ? 'bat' : 'sh'}`,
};
config.env = {
...config.env,
VSCODE_SKIP_PRELAUNCH: '1',
};
} else {
// web configs not supported, yet
}
return config;
}));
export default config;
================================================
FILE: CodeQL.yml
================================================
path_classifiers:
test:
# Classify all files in the top-level directories test/ and testsuites/ as test code.
- test
# Classify all files with suffix `.test` as test code.
# Note: use only forward slash / as a path separator.
# * Matches any sequence of characters except a forward slash.
# ** Matches any sequence of characters, including a forward slash.
# This wildcard must either be surrounded by forward slash symbols, or used as the first segment of a path.
# It matches zero or more whole directory segments. There is no need to use a wildcard at the end of a directory path because all sub-directories are automatically matched.
# That is, /anything/ matches the anything directory and all its subdirectories.
# Always enclose the expression in double quotes if it includes *.
- "**/*.test.ts"
# The default behavior is to tag all files created during the
# build as `generated`. Results are hidden for generated code. You can tag
# further files as being generated by adding them to the `generated` section.
generated:
# generated code.
- out
- "out-build"
- "out-vscode"
- "**/out/**"
- ".build/distro/cli-patches/index.js"
# The default behavior is to tag library code as `library`. Results are hidden
# for library code. You can tag further files as being library code by adding them
# to the `library` section.
library:
- "**/node_modules/**"
================================================
FILE: HOW_TO_CONTRIBUTE.md
================================================
# Contributing to Void
### Welcome! 👋
This is the official guide on how to contribute to Void. We want to make it as easy as possible to contribute, so if you have any questions or comments, reach out via email or discord!
There are a few ways to contribute:
- 💫 Complete items on the [Roadmap](https://github.com/orgs/voideditor/projects/2).
- 💡 Make suggestions in our [Discord](https://discord.gg/RSNjgaugJs).
- 🪴 Start new Issues - see [Issues](https://github.com/voideditor/void/issues).
### Codebase Guide
We [highly recommend reading this](https://github.com/voideditor/void/blob/main/VOID_CODEBASE_GUIDE.md) guide that we put together on Void's sourcecode if you'd like to add new features.
The repo is not as intimidating as it first seems if you read the guide!
Most of Void's code lives in the folder `src/vs/workbench/contrib/void/`.
## Editing Void's Code
If you're making changes to Void's code as a contributor, you'll want to run a local version of Void to make sure your changes worked. Developer mode lets you do this. Here's how to use it.
### a. Mac - Prerequisites
If you're using a Mac, you need Python and XCode. You probably have these by default.
### b. Windows - Prerequisites
If you're using a Windows computer, first get [Visual Studio 2022](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community) (recommended) or [VS Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) (not recommended). If you already have both, you might need to run the next few steps on both of them.
Go to the "Workloads" tab and select:
- `Desktop development with C++`
- `Node.js build tools`
Go to the "Individual Components" tab and select:
- `MSVC v143 - VS 2022 C++ x64/x86 Spectre-mitigated libs (Latest)`
- `C++ ATL for latest build tools with Spectre Mitigations`
- `C++ MFC for latest build tools with Spectre Mitigations`
Finally, click Install.
### c. Linux - Prerequisites
First, run `npm install -g node-gyp`. Then:
- Debian (Ubuntu, etc): `sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev libkrb5-dev python-is-python3`.
- Red Hat (Fedora, etc): `sudo dnf install @development-tools gcc gcc-c++ make libsecret-devel krb5-devel libX11-devel libxkbfile-devel`.
- SUSE (openSUSE, etc): `sudo zypper install patterns-devel-C-C++-devel_C_C++ krb5-devel libsecret-devel libxkbfile-devel libX11-devel`.
- Others: see [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute).
### Developer Mode Instructions
Here's how to start changing Void's code. These steps cover everything from cloning Void, to opening a Developer Mode window where you can play around with your updates.
1. `git clone https://github.com/voideditor/void` to clone the repo.
2. `npm install` to install all dependencies.
3. Open Void or VSCode, and initialize Developer Mode (this can take ~5 min to finish, it's done when 2 of the 3 spinners turn to check marks):
- Windows: Press Ctrl+Shift+B.
- Mac: Press Cmd+Shift+B.
- Linux: Press Ctrl+Shift+B.
4. Open the Void Developer Mode window:
- Windows: `./scripts/code.bat`.
- Mac: `./scripts/code.sh`.
- Linux: `./scripts/code.sh`.
5. You're good to start editing Void's code!
- You won't see your changes unless you press Ctrl+R (Cmd+R) inside the new window to reload. Alternatively, press Ctrl+Shift+P and `Reload Window`.
- You might want to add the flags `--user-data-dir ./.tmp/user-data --extensions-dir ./.tmp/extensions` to the command in step 4, which lets you reset any IDE changes you made by deleting the `.tmp` folder.
- You can kill any of the build scripts by pressing `Ctrl+D` in its terminal. If you press `Ctrl+C` the script will close but will keep running in the background.
If you get any errors, scroll down for common fixes.
#### Common Fixes
- Make sure you followed the prerequisite steps above.
- Make sure you have Node version `20.18.2` (the version in `.nvmrc`).
- You can do this without changing your global Node version using [nvm](https://github.com/nvm-sh/nvm): run `nvm install`, followed by `nvm use` to install the version in `.nvmrc` locally.
- Make sure the path to your Void folder does not have any spaces in it.
- If you get `"TypeError: Failed to fetch dynamically imported module"`, make sure all imports end with `.js`.
- If you get an error with React, try running `NODE_OPTIONS="--max-old-space-size=8192" npm run buildreact`.
- If you see missing styles, wait a few seconds and then reload.
- If you get errors like `npm error libtool: error: unrecognised option: '-static'`, when running ./scripts/code.sh, make sure you have GNU libtool instead of BSD libtool (BSD is the default in macos)
- If you get errors like `The SUID sandbox helper binary was found, but is not configured correctly` when running ./scripts/code.sh, run
`sudo chown root:root .build/electron/chrome-sandbox && sudo chmod 4755 .build/electron/chrome-sandbox` and then run `./scripts/code.sh` again.
- If you have any other questions, feel free to [submit an issue](https://github.com/voideditor/void/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
#### Building Void from Terminal
To build Void from the terminal instead of from inside VSCode, follow the steps above, but instead of pressing Cmd+Shift+B, run `npm run watch`. The build is done when you see something like this:
```
[watch-extensions] [00:37:39] Finished compilation extensions with 0 errors after 19303 ms
[watch-client ] [00:38:06] Finished compilation with 0 errors after 46248 ms
[watch-client ] [00:38:07] Starting compilation...
[watch-client ] [00:38:07] Finished compilation with 0 errors after 5 ms
```
### Distributing
Void's maintainers distribute Void on our website and in releases. Our build pipeline is a fork of VSCodium, and it works by running GitHub Actions which create the downloadables. The build repo with more instructions lives [here](https://github.com/voideditor/void-builder).
If you want to completely control Void's build pipeline for your own internal usage, which comes with a lot of time cost (and is typically not recommended), see our [`void-builder`](https://github.com/voideditor/void-builder) repo which builds Void and contains a few important notes about auto-updating and rebasing.
#### Building a Local Executible
We don't usually recommend building a local executible of Void - typically you should follow the steps above to distribute a complete executible with the advantages of VSCodium baked-in, or you should just use Developer Mode to run Void locally which is much faster. If you're certain this is what you want, see details below.
Building Locally (not recommended)
If you're certain you want to build a local executible of Void, follow these steps. It can take ~25 minutes.
Make sure you've already entered Developer Mode with Void first, then run one of the following commands. This will create a folder named `VSCode-darwin-arm64` or similar outside of the void/ repo (see below).
##### Mac
- `npm run gulp vscode-darwin-arm64` - most common (Apple Silicon)
- `npm run gulp vscode-darwin-x64` (Intel)
##### Windows
- `npm run gulp vscode-win32-x64` - most common
- `npm run gulp vscode-win32-arm64`
##### Linux
- `npm run gulp vscode-linux-x64` - most common
- `npm run gulp vscode-linux-arm64`
##### Local Executible Output
The local executible will be located in a folder outside of `void/`:
```bash
workspace/
├── void/ # Your Void fork
└── VSCode-darwin-arm64/ # Generated output
```
## Pull Request Guidelines
- Please submit a pull request once you've made a change.
- No need to submit an Issue unless you're creating a new feature that might involve multiple PRs.
- Please don't use AI to write your PR 🙂
================================================
FILE: LICENSE-VS-Code.txt
================================================
Void is a fork of VS Code, which is licensed under the MIT License (below).
Void's additions and modifications are licensed under the Apache 2.0 License (see LICENSE.txt).
--------------------
MIT License
Copyright (c) 2015 - present Microsoft Corporation
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.
================================================
FILE: LICENSE.txt
================================================
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 2025 Glass Devtools, Inc.
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.
================================================
FILE: README.md
================================================
# Welcome to Void.
Void is the open-source Cursor alternative.
Use AI agents on your codebase, checkpoint and visualize changes, and bring any model or host locally. Void sends messages directly to providers without retaining your data.
This repo contains the full sourcecode for Void. If you're new, welcome!
- 🧭 [Website](https://voideditor.com)
- 👋 [Discord](https://discord.gg/RSNjgaugJs)
- 🚙 [Project Board](https://github.com/orgs/voideditor/projects/2)
## Note
We've paused work on the Void IDE (this repo) to explore a few novel coding ideas. We want to focus on innovation over feature-parity. Void will continue running, but without maintenance some existing features might stop working over time. Depending on the direction of our new work, we might not resume Void as an IDE.
We won't be actively reviewing Issues and PRs, but we will respond to all [email](mailto:hello@voideditor.com) inquiries on building and maintaining your own version of Void while we're paused.
## Reference
Void is a fork of the [vscode](https://github.com/microsoft/vscode) repository. For a guide to the codebase, see [VOID_CODEBASE_GUIDE](https://github.com/voideditor/void/blob/main/VOID_CODEBASE_GUIDE.md).
For a guide on how to develop your own version of Void, see [HOW_TO_CONTRIBUTE](https://github.com/voideditor/void/blob/main/HOW_TO_CONTRIBUTE.md) and [void-builder](https://github.com/voideditor/void-builder).
## Support
You can always reach us in our Discord server or contact us via email: hello@voideditor.com.
================================================
FILE: ThirdPartyNotices.txt
================================================
NOTICES
This repository incorporates material as listed below or described in the code.
---------------------------------------------------------
@fig/autocomplete-shared 1.1.2
https://github.com/withfig/autocomplete-tools
MIT License
Copyright (c) 2021 Hercules Labs Inc. (Fig)
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.
---------------------------------------------------------
---------------------------------------------------------
@iktakahiro/markdown-it-katex 4.0.2 - MIT
https://github.com/mjbvz/markdown-it-katex
The MIT License (MIT)
Copyright (c) 2016 Waylon Flinn
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.
---
The MIT License (MIT)
Copyright (c) 2018 Takahiro Ethan Ikeuchi @iktakahiro
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.
---------------------------------------------------------
---------------------------------------------------------
amazon-q-developer-cli f66e0b0e917ab185eef528dc36eca56b78ca8b5d
https://github.com/aws/amazon-q-developer-cli
MIT License
Copyright (c) 2024 Amazon.com, Inc. or its affiliates.
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.
---------------------------------------------------------
---------------------------------------------------------
atom/language-clojure 0.22.8 - MIT
https://github.com/atom/language-clojure
Copyright (c) 2014 GitHub Inc.
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.
This package was derived from a TextMate bundle located at
https://github.com/mmcgrana/textmate-clojure and distributed under the
following license, located in `LICENSE.md`:
The MIT License (MIT)
Copyright (c) 2010- Mark McGranaghan
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.
---------------------------------------------------------
---------------------------------------------------------
atom/language-coffee-script 0.49.3 - MIT
https://github.com/atom/language-coffee-script
The MIT License (MIT)
Copyright (c) 2014 GitHub Inc.
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.
This package was derived from a TextMate bundle located at
https://github.com/jashkenas/coffee-script-tmbundle and distributed under the
following license, located in `LICENSE`:
Copyright (c) 2009-2014 Jeremy Ashkenas
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.
---------------------------------------------------------
---------------------------------------------------------
atom/language-sass 0.61.4 - MIT
https://github.com/atom/language-sass
The MIT License (MIT)
Copyright (c) 2014 GitHub Inc.
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.
This package was derived from a TextMate bundle located at
https://github.com/alexsancho/Sass.tmbundle and distributed under the following
license, located in `LICENSE.md`:
Copyright (c) 2012 Alex Sancho, http://alexsancho.name/
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.
---------------------------------------------------------
---------------------------------------------------------
atom/language-xml 0.35.2 - MIT
https://github.com/atom/language-xml
The MIT License (MIT)
Copyright (c) 2014 GitHub Inc.
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.
This package was derived from a TextMate bundle located at
https://github.com/textmate/xml.tmbundle and distributed under the following
license, located in `README.mdown`:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
---------------------------------------------------------
---------------------------------------------------------
autocomplete 2.684.0 - MIT
https://github.com/withfig/autocomplete
MIT License
Copyright (c) 2021 Hercules Labs Inc. (Fig)
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.
---------------------------------------------------------
---------------------------------------------------------
cacheable-request 7.0.4 - MIT
Copyright (c) cacheable-request authors
MIT License
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.
---------------------------------------------------------
---------------------------------------------------------
Colorsublime-Themes 0.1.0
https://github.com/Colorsublime/Colorsublime-Themes
Copyright (c) 2015 Colorsublime.com
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.
---------------------------------------------------------
---------------------------------------------------------
daaain/Handlebars 1.8.0 - MIT
https://github.com/daaain/Handlebars
-- Credits
Adapted from the great sublime-text-handlebars package by Nicholas Westlake.
Thanks a lot to all the generous contributors (in alphabetical order): @bittersweetryan, @bradcliffe, @calumbrodie, @duncanbeevers, @hlvnst, @jonschlinkert, @Krutius, @samselikoff, @utkarshkukreti, @zeppelin
-- License
(The MIT License)
Copyright (c) daaain/Handlebars project authors
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.
---------------------------------------------------------
---------------------------------------------------------
dart-lang/dart-syntax-highlight 0.0.0 - BSD
https://github.com/dart-lang/dart-syntax-highlight
Copyright 2020, the Dart project authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------
---------------------------------------------------------
davidrios/pug-tmbundle 0.0.0 - MIT
https://github.com/davidrios/pug-tmbundle
The MIT License (MIT)
Copyright (c) 2016 David Rios
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.
---------------------------------------------------------
---------------------------------------------------------
definitelytyped - MIT
https://github.com/DefinitelyTyped/DefinitelyTyped
This project is licensed under the MIT license.
Copyrights are respective of each contributor listed at the beginning of each definition file.
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.
---------------------------------------------------------
---------------------------------------------------------
Document Object Model 4.0.0 - W3C License
https://www.w3.org/DOM/
W3C License
This work is being provided by the copyright holders under the following license.
By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions.
Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following
on ALL copies of the work or portions thereof, including modifications:
* The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
* Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included.
* Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived
from Document Object Model. Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang)."
Disclaimers
THIS WORK IS PROVIDED "AS IS
AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR
FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission.
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.
---------------------------------------------------------
---------------------------------------------------------
dotnet/csharp-tmLanguage 0.1.0 - MIT
https://github.com/dotnet/csharp-tmLanguage
MIT License
Copyright (c) 2016 .NET Foundation
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.
---------------------------------------------------------
---------------------------------------------------------
dotnet/razor 1.0.0 - MIT
https://github.com/dotnet/razor
MIT License
Copyright (c) .NET Foundation and Contributors
All Rights Reserved
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.
---------------------------------------------------------
---------------------------------------------------------
expand-abbreviation 0.5.8 - MIT
https://github.com/emmetio/expand-abbreviation
MIT License
Copyright (c) 2017 Emmet.io
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.
---------------------------------------------------------
---------------------------------------------------------
fadeevab/make.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/fadeevab/make.tmbundle
Copyright (c) textmate-make.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
fish-shell 3.7.1
https://github.com/fish-shell/fish-shell
Fish is a smart and user-friendly command line shell.
Copyright (C) 2005-2009 Axel Liljencrantz
Copyright (C) 2009- fish-shell contributors
fish is free software.
Most of fish is licensed under the GNU General Public License version 2, and
you can redistribute it and/or modify it under the terms of the GNU GPL as
published by the Free Software Foundation.
fish also includes software licensed under the Python Software Foundation License version 2, the MIT
license, and the GNU Library General Public License version 2.
Full licensing information is contained in doc_src/license.rst.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
---------------------------------------------------------
---------------------------------------------------------
go-syntax 0.7.9 - MIT
https://github.com/worlpaker/go-syntax
MIT License
Copyright (c) 2023 Furkan Ozalp
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.
---------------------------------------------------------
---------------------------------------------------------
HTML 5.1 W3C Working Draft 08 October 2015 - W3C Document License
http://www.w3.org/TR/2015/WD-html51-20151008/
Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang). This software or document includes material copied
from or derived from HTML 5.1 W3C Working Draft (http://www.w3.org/TR/2015/WD-html51-20151008/.)
THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT
NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF
THE DOCUMENT ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY
PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE
DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to this document or its contents
without specific, written prior permission. Title to copyright in this document will at all times remain with copyright holders.
---------------------------------------------------------
---------------------------------------------------------
Ionic documentation 1.2.4 - Apache-2.0
https://github.com/ionic-team/ionic-site
Copyright Drifty Co. http://drifty.com/.
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:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
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
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
---------------------------------------------------------
---------------------------------------------------------
ionide/ionide-fsgrammar 0.0.0 - MIT
https://github.com/ionide/ionide-fsgrammar
The MIT License (MIT)
Copyright (c) 2015 Krzysztof Cieslak
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.
---------------------------------------------------------
---------------------------------------------------------
James-Yu/LaTeX-Workshop 8.19.1 - MIT
https://github.com/James-Yu/LaTeX-Workshop
The MIT License (MIT)
Copyright (c) 2016 James Yu
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.
---------------------------------------------------------
---------------------------------------------------------
jeff-hykin/better-c-syntax 1.13.2 - MIT
https://github.com/jeff-hykin/better-c-syntax
MIT License
Copyright (c) 2019 Jeff Hykin
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.
---------------------------------------------------------
---------------------------------------------------------
jeff-hykin/better-cpp-syntax 1.17.4 - MIT
https://github.com/jeff-hykin/better-cpp-syntax
MIT License,,Copyright (c) 2019 Jeff Hykin,,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.
---------------------------------------------------------
---------------------------------------------------------
jeff-hykin/better-objc-syntax 0.2.0 - MIT
https://github.com/jeff-hykin/better-objc-syntax
MIT License
Copyright (c) 2019 Jeff Hykin
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.
---------------------------------------------------------
---------------------------------------------------------
jeff-hykin/better-objcpp-syntax 0.1.0 - MIT
https://github.com/jeff-hykin/better-objcpp-syntax
MIT License
Copyright (c) 2019 Jeff Hykin
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.
---------------------------------------------------------
---------------------------------------------------------
jeff-hykin/better-shell-syntax 1.8.7 - MIT
https://github.com/jeff-hykin/better-shell-syntax
MIT License
Copyright (c) 2019 Jeff Hykin
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.
---------------------------------------------------------
---------------------------------------------------------
jeff-hykin/better-snippet-syntax 1.0.2 - MIT
https://github.com/jeff-hykin/better-snippet-syntax
MIT License
Copyright (c) 2019 Jeff Hykin
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.
---------------------------------------------------------
---------------------------------------------------------
jlelong/vscode-latex-basics 1.9.0 - MIT
https://github.com/jlelong/vscode-latex-basics
Copyright (c) vscode-latex-basics authors
If not otherwise specified (see below), files in this repository fall under the MIT License
The file syntaxes/LaTeX.tmLanguage.json is based on https://github.com/textmate/latex.tmbundle/blob/master/Syntaxes/LaTeX.plist
but has been largely modified. The original file falls under the following license
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
The file syntaxes/markdown-latex-combined.tmLanguage.json is generated from the Markdown grammar
included in VSCode and falls under the license described in markdown-latex-combined-license.txt.
The file syntaxes/cpp-grammar-bailout.tmLanguage.json is generated from https://github.com/jeff-hykin/better-cpp-syntax
and falls under the license described in cpp-bailout-license.txt.
---------------------------------------------------------
---------------------------------------------------------
js-beautify 1.6.8 - MIT
https://github.com/beautify-web/js-beautify
The MIT License (MIT)
Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and 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.
---------------------------------------------------------
---------------------------------------------------------
jtbandes/swift-tmlanguage - MIT
https://github.com/jtbandes/swift-tmlanguage
The MIT License (MIT)
Copyright 2023 Jacob Bandes-Storch
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.
---------------------------------------------------------
---------------------------------------------------------
JuliaEditorSupport/atom-language-julia 0.23.0 - MIT
https://github.com/JuliaEditorSupport/atom-language-julia
The atom-language-julia package is licensed under the MIT "Expat" License:
> Copyright (c) 2015
>
> 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.
---------------------------------------------------------
---------------------------------------------------------
Jxck/assert 1.0.0 - MIT
https://github.com/Jxck/assert
The MIT License (MIT)
Copyright (c) 2011 Jxck
Originally from node.js (http://nodejs.org)
Copyright Joyent, Inc.
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.
---------------------------------------------------------
---------------------------------------------------------
language-docker 0.0.0 - Apache-2.0
https://github.com/moby/moby
Apache License
Version 2.0, January 2004
https://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
Copyright 2013-2018 Docker, Inc.
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
https://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.
---------------------------------------------------------
---------------------------------------------------------
language-less 0.6.1 - MIT
https://github.com/radium-v/Better-Less
MIT License
Copyright (c) 2017 John Kreitlow
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.
---------------------------------------------------------
---------------------------------------------------------
language-php 0.49.0 - MIT
https://github.com/KapitanOczywisty/language-php
The MIT License (MIT)
Copyright (c) 2014 GitHub Inc.
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.
This package was derived from a TextMate bundle located at
https://github.com/textmate/php.tmbundle and distributed under the following
license, located in `README.mdown`:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
---------------------------------------------------------
---------------------------------------------------------
MagicStack/MagicPython 1.1.1 - MIT
https://github.com/MagicStack/MagicPython
The MIT License
Copyright (c) 2015-present MagicStack Inc. http://magic.io
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.
---------------------------------------------------------
---------------------------------------------------------
marked 14.0.0 - MIT
https://github.com/markedjs/marked
information
## Contribution License Agreement
If you contribute code to this project, you are implicitly allowing your code
to be distributed under the MIT license. You are also implicitly verifying that
all code is your original work. ``
## Marked
Copyright (c) 2018+, MarkedJS (https://github.com/markedjs/)
Copyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/)
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.
## Markdown
Copyright © 2004, John Gruber
http://daringfireball.net/
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name "Markdown" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
---------------------------------------------------------
---------------------------------------------------------
microsoft/TypeScript-TmLanguage 0.0.1 - MIT
https://github.com/microsoft/TypeScript-TmLanguage
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
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.
---------------------------------------------------------
---------------------------------------------------------
microsoft/vscode-css 0.0.0 - MIT License
https://github.com/microsoft/vscode-css
MIT License
Copyright (c) Microsoft Corporation.
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.
--------------------------------------------------------------------
This package was derived from a TextMate bundle located at
https://github.com/textmate/css.tmbundle and distributed under the following
license, located in `README.mdown`:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
---------------------------------------------------------
---------------------------------------------------------
microsoft/vscode-JSON.tmLanguage 0.0.0 - MIT
https://github.com/microsoft/vscode-JSON.tmLanguage
vscode-JSON.tmLanguage
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
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.
---------------------------------------------------------
---------------------------------------------------------
microsoft/vscode-markdown-tm-grammar 1.0.0 - MIT
https://github.com/microsoft/vscode-markdown-tm-grammar
The MIT License (MIT)
Copyright (c) Microsoft 2018
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.
---------------------------------------------------------
---------------------------------------------------------
microsoft/vscode-mssql 1.29.0 - MIT
https://github.com/microsoft/vscode-mssql
------------------------------------------ START OF LICENSE -----------------------------------------
vscode-mssql
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
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:
Copyright (c) 2016 Microsoft
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.
----------------------------------------------- END OF LICENSE -----------------------------------------
---------------------------------------------------------
---------------------------------------------------------
mmims/language-batchfile 0.7.6 - MIT
https://github.com/mmims/language-batchfile
The MIT License (MIT)
Copyright (c) 2021 Michael Mims
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.
---------------------------------------------------------
---------------------------------------------------------
NVIDIA/cuda-cpp-grammar 0.0.0 - MIT
https://github.com/NVIDIA/cuda-cpp-grammar
The MIT License (MIT)
Copyright 2021 NVIDIA Corporation
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.
---------------------------------------------------------
---------------------------------------------------------
PowerShell/EditorSyntax 1.0.0 - MIT
https://github.com/PowerShell/EditorSyntax
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
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.
---------------------------------------------------------
---------------------------------------------------------
RedCMD/YAML-Syntax-Highlighter 1.3.2 - MIT
https://github.com/RedCMD/YAML-Syntax-Highlighter
MIT License
Copyright 2024 RedCMD
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.
---------------------------------------------------------
---------------------------------------------------------
redhat-developer/vscode-java 1.26.0 - MIT
https://github.com/redhat-developer/vscode-java
The MIT License (MIT)
Copyright (c) 2014 GitHub Inc.
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.
--------------------------------------------------------------------
This package was derived from a TextMate bundle located at
https://github.com/textmate/java.tmbundle and distributed under the following
license, located in `README.mdown`:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
---------------------------------------------------------
---------------------------------------------------------
REditorSupport/vscode-R 2.8.4 - MIT
https://github.com/REditorSupport/vscode-R
MIT License
Copyright (c) 2022 REditorSupport
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.
---------------------------------------------------------
---------------------------------------------------------
rust-syntax 0.6.1 - MIT
https://github.com/dustypomerleau/rust-syntax
MIT License
Copyright (c) 2020 Dustin Pomerleau
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.
---------------------------------------------------------
---------------------------------------------------------
semver 5.5.0 - The ISC License
https://github.com/npm/node-semver
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------
---------------------------------------------------------
seti-ui 0.1.0
https://github.com/jesseweed/seti-ui
Copyright (c) 2014 Jesse Weed
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.
---------------------------------------------------------
---------------------------------------------------------
shaders-tmLanguage 0.1.0 - MIT
https://github.com/tgjones/shaders-tmLanguage
MIT License
Copyright (c) 2017 Tim Jones
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.
---------------------------------------------------------
---------------------------------------------------------
Shopify/ruby-lsp 0.0.0 - MIT License
https://github.com/Shopify/ruby-lsp
The MIT License (MIT)
Copyright (c) 2022-present, Shopify Inc.
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.
================================================================================
The following files and related configuration in package.json are based on a
sequence of adaptions: grammars/ruby.cson.json, grammars/erb.cson.json,
languages/erb.json.
Copyright (c) 2016 Peng Lv
Copyright (c) 2017-2019 Stafford Brunk
https://github.com/rubyide/vscode-ruby
Released under the MIT license
https://github.com/rubyide/vscode-ruby/blob/main/LICENSE.txt
Copyright (c) 2014 GitHub Inc.
https://github.com/atom/language-ruby
Released under the MIT license
https://github.com/atom/language-ruby/blob/master/LICENSE.md
https://github.com/textmate/ruby.tmbundle
https://github.com/textmate/ruby.tmbundle#license
---------------------------------------------------------
---------------------------------------------------------
sumneko/lua.tmbundle 1.0.0 - TextMate Bundle License
https://github.com/sumneko/lua.tmbundle
Copyright (c) sumneko-lua.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/asp.vb.net.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/asp.vb.net.tmbundle
Copyright (c) textmate-asp.vb.net.tmbundle project authors
If not otherwise specified (see below), files in this folder fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/c.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/c.tmbundle
Copyright (c) textmate-c.tmbundle authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/diff.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/diff.tmbundle
Copyright (c) textmate-diff.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/git.tmbundle 0.0.0 - MIT
https://github.com/textmate/git.tmbundle
The MIT License (MIT)
Copyright (c) 2008 Tim Harper
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.
---------------------------------------------------------
---------------------------------------------------------
textmate/groovy.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/groovy.tmbundle
Copyright (c) textmate-groovy.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/html.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/html.tmbundle
Copyright (c) textmate-html.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/ini.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/ini.tmbundle
Copyright (c) textmate-ini.tmbundle project authors
If not otherwise specified (see below), files in this folder fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/javascript.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/javascript.tmbundle
Copyright (c) textmate-javascript.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/markdown.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/markdown.tmbundle
Copyright (c) markdown.tmbundle authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
textmate/perl.tmbundle 0.0.0 - TextMate Bundle License
https://github.com/textmate/perl.tmbundle
Copyright (c) textmate-perl.tmbundle project authors
If not otherwise specified (see below), files in this repository fall under the following license:
Permission to copy, use, modify, sell and distribute this
software is granted. This software is provided "as is" without
express or implied warranty, and with no claim as to its
suitability for any purpose.
An exception is made for files in readable text which contain their own license information,
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
to the base-name name of the original file, and an extension of txt, html, or similar. For example
"tidy" is accompanied by "tidy-license.txt".
---------------------------------------------------------
---------------------------------------------------------
trond-snekvik/vscode-rst 1.5.3 - MIT
https://github.com/trond-snekvik/vscode-rst
The MIT License (MIT)
Copyright 2021 Trond Snekvik
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.
---------------------------------------------------------
---------------------------------------------------------
TypeScript-TmLanguage 0.1.8 - MIT
TypeScript-TmLanguage 1.0.0 - MIT
https://github.com/microsoft/TypeScript-TmLanguage
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
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.
---------------------------------------------------------
---------------------------------------------------------
Unicode 12.0.0 - UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
https://home.unicode.org/
Unicode Data Files include all data files under the directories
https://www.unicode.org/Public/, https://www.unicode.org/reports/,
https://cldr.unicode.org, https://github.com/unicode-org/icu, and
https://www.unicode.org/utility/trac/browser/.
Unicode Data Files do not include PDF online code charts under the
directory https://www.unicode.org/Public/.
Software includes any source code published in the Unicode Standard
or under the directories
https://www.unicode.org/Public/, https://www.unicode.org/reports/,
https://cldr.unicode.org, https://github.com/unicode-org/icu, and
https://www.unicode.org/utility/trac/browser/.
NOTICE TO USER: Carefully read the following legal agreement.
BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT.
IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
THE DATA FILES OR SOFTWARE.
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1991-2017 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Unicode data files and any associated documentation
(the "Data Files") or Unicode software and any associated documentation
(the "Software") to deal in the Data Files or Software
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, and/or sell copies of
the Data Files or Software, and to permit persons to whom the Data Files
or Software are furnished to do so, provided that either
(a) this copyright and permission notice appear with all copies
of the Data Files or Software, or
(b) this copyright and permission notice appear in associated
Documentation.
THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THE DATA FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in these Data Files or Software without prior
written authorization of the copyright holder.
---------------------------------------------------------
---------------------------------------------------------
vscode-codicons 0.0.14 - MIT and Creative Commons Attribution 4.0
https://github.com/microsoft/vscode-codicons
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the "Licensor." The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
---------------------------------------------------------
---------------------------------------------------------
vscode-logfile-highlighter 3.3.4 - MIT
https://github.com/emilast/vscode-logfile-highlighter
The MIT License (MIT)
Copyright (c) 2015 emilast
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.
---------------------------------------------------------
---------------------------------------------------------
vscode-swift 0.0.1 - MIT
https://github.com/owensd/vscode-swift
The MIT License (MIT)
Copyright (c) 2015 David Owens II
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.
---------------------------------------------------------
---------------------------------------------------------
vscode-win32-app-container-tokens
https://github.com/microsoft/vscode-win32-app-container-tokens
MIT License
Copyright (c) Microsoft Corporation.
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
---------------------------------------------------------
---------------------------------------------------------
walles/git-commit-message-plus 1.0.0 - MIT
https://github.com/walles/git-commit-message-plus
The MIT License (MIT)
Copyright (c) 2023 Johan Walles
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.
---------------------------------------------------------
---------------------------------------------------------
Web Background Synchronization - Apache-2.0
https://github.com/WICG/background-sync
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.
---------------------------------------------------------
---------------------------------------------------------
zsh 5.9
https://github.com/zsh-users/zsh
Unless otherwise noted in the header of specific files, files in this distribution have the licence shown below.
However, note that certain shell functions are licensed under versions of the GNU General Public Licence. Anyone distributing the shell as a binary including those files needs to take account of this. Search shell functions for "Copyright" for specific copyright information. None of the core functions are affected by this, so those files may simply be omitted.
--
The Z Shell is copyright (c) 1992-2017 Paul Falstad, Richard Coleman, Zoltán Hidvégi, Andrew Main, Peter Stephenson, Sven Wischnowsky, and others. All rights reserved. Individual authors, whether or not specifically named, retain copyright in all changes; in what follows, they are referred to as `the Zsh Development Group'. This is for convenience only and this body has no legal status. The Z shell is distributed under the following licence; any provisions made in individual files take precedence.
Permission is hereby granted, without written agreement and without licence or royalty fees, to use, copy, modify, and distribute this software and to distribute modified versions of this software for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software.
In no event shall the Zsh Development Group be liable to any party for direct, indirect, special, incidental, or consequential damages arising out of the use of this software and its documentation, even if the Zsh Development Group have been advised of the possibility of such damage.
The Zsh Development Group specifically disclaim any warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The software provided hereunder is on an "as is" basis, and the Zsh Development Group have no obligation to provide maintenance, support, updates, enhancements, or modifications.
---------------------------------------------------------
================================================
FILE: VOID_CODEBASE_GUIDE.md
================================================
# Void Codebase Guide
The Void codebase is not as intimidating as it seems!
Most of Void's code lives in the folder `src/vs/workbench/contrib/void/`.
The purpose of this document is to explain how Void's codebase works. If you want build instructions instead, see [Contributing](https://github.com/voideditor/void/blob/main/HOW_TO_CONTRIBUTE.md).
## Void Codebase Guide
### VSCode Rundown
Here's a VSCode rundown if you're just getting started with Void. You can also see Microsoft's [wiki](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) for some pictures. VSCode is an Electron app. Electron runs two processes: a **main** process (for internals) and a **browser** process (browser means HTML in general, not just "web browser").
- Code in a `browser/` folder always lives on the browser process, and it can use `window` and other browser items.
- Code in an `electron-main/` folder always lives on the main process, and it can import `node_modules`.
- Code in `common/` can be used by either process, but doesn't get any special imports.
- The browser environment is not allowed to import `node_modules`. We came up with two workarounds:
1. Bundle the raw node_module code to the browser - we're doing this for React.
2. Implement the code on `electron-main/` and set up a channel between main/browser - we're doing this for sendLLMMessage.
### Terminology
Here's some terminology you might want to know about when working inside VSCode:
- An **Editor** is the thing that you type your code in. If you have 10 tabs open, that's just one editor! Editors contain tabs (or "models").
- A **Model** is an internal representation of a file's contents. It's shared between editors (for example, if you press `Cmd+\` to make a new editor, then the model of a file like `A.ts` is shared between them. Two editors, one model. That's how changes sync.).
- Each model has a **URI** it represents, like `/Users/.../my_file.txt`. (A URI or "resource" is generally just a path).
- The **Workbench** is the wrapper that contains all the editors, the terminal, the file system tree, etc.
- Usually you use the `ITextModel` type for models and the `ICodeEditor` type for editors. There aren't that many other types.
- VSCode is organized into "**Services**". A service is just a class that mounts a single time (in computer science theory this is called a "singleton"). You can register services with `registerSingleton` so that you can easily use them in any constructor with `@`. See _dummyContrib for an example we put together on how to register them. The registration is the same every time.
- "**Actions**" are functions you register on VSCode so that either you or the user can call them later. They're also called "**Commands**".
- You can run actions as a user by pressing Cmd+Shift+P (opens the command pallete), or you can run them internally by using the commandService to call them by ID. We use actions to register keybinding listeners like Cmd+L, Cmd+K, etc. The nice thing about actions is the user can change the keybindings.
### Internal LLM Message Pipeline
Here's a picture of all the dependencies that are relevent between the time you first send a message through Void's sidebar, and the time a request is sent to your provider.
Sending LLM messages from the main process avoids CSP issues with local providers and lets us use node_modules more easily.
**Notes:** `modelCapabilities` is an important file that must be updated when new models come out!
### Apply
Void has two types of Apply: **Fast Apply** (uses Search/Replace, see below), and **Slow Apply** (rewrites whole file).
When you click Apply and Fast Apply is enabled, we prompt the LLM to output Search/Replace block(s) like this:
```
<<<<<<< ORIGINAL
// original code goes here
=======
// replaced code goes here
>>>>>>> UPDATED
```
This is what allows Void to quickly apply code even on 1000-line files. It's the same as asking the LLM to press Ctrl+F and enter in a search/replace query.
### Apply Inner Workings
The `editCodeService` file runs Apply. The same exact code is also used when the LLM calls the Edit tool, and when you submit Cmd+K. Just different versions of Fast/Slow Apply mode.
Here is some important terminology:
- A **DiffZone** is a {startLine, endLine} region of text where we compute and show red/green areas, or **Diffs**. When any changes are made to a file, we loop through all the DiffAreas on that file and refresh its Diffs.
- A **DiffArea** is a generalization that just tracks line numbers like a DiffZone.
- The only type of DiffArea that can "stream" is a DiffZone. Each DiffZone has an llmCancelToken if it's streaming.
How Apply works:
- When you click Apply, we create a **DiffZone** over that the full file so that any changes that the LLM makes will show up in red/green. We then stream the change.
- When an LLM calls Edit, it's really calling Apply.
- When you submit Cmd+K, it's the same as Apply except we create a smaller DiffZone (not on the whole file).
### Writing Files Inner Workings
When Void wants to change your code, it just writes to a text model. This means all you need to know to write to a file is its URI - you don't have to load it, save it, etc. There are some annoying background URI/model things to think about to get this to work, but we handled them all in `voidModelService`.
### Void Settings Inner Workings
We have a service `voidSettingsService` that stores all your Void settings (providers, models, global Void settings, etc). Imagine this as an implicit dependency for any of the core Void services:
Here's a guide to some of the terminology we're using:
- **FeatureName**: Autocomplete | Chat | CtrlK | Apply
- **ModelSelection**: a {providerName, modelName} pair.
- **ProviderName**: The name of a provider: `'ollama'`, `'openAI'`, etc.
- **ModelName**: The name of a model (string type, eg `'gpt-4o'`).
- **RefreshProvider**: a provider that we ping repeatedly to update the models list.
- **ChatMode** = normal | gather | agent
### Approval State
`editCodeService`'s data structures contain all the information about changes that the user needs to review. However, they don't store that information in a useful format. We wrote the following service to get a more useful derived state:
### Build process
If you want to know how our build pipeline works, see our build repo [here](https://github.com/voideditor/void-builder).
## VSCode Codebase Guide
For additional references, the Void team put together this list of links to get up and running with VSCode.
#### Links for Beginners
- [VSCode UI guide](https://code.visualstudio.com/docs/getstarted/userinterface) - covers auxbar, panels, etc.
- [UX guide](https://code.visualstudio.com/api/ux-guidelines/overview) - covers Containers, Views, Items, etc.
#### Links for Contributors
- [How VSCode's sourcecode is organized](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) - this explains where the entry point files are, what `browser/` and `common/` mean, etc. This is the most important read on this whole list! We recommend reading the whole thing.
- [Built-in VSCode styles](https://code.visualstudio.com/api/references/theme-color) - CSS variables that are built into VSCode. Use `var(--vscode-{theme but replacing . with -})`. You can also see their [Webview theming guide](https://code.visualstudio.com/api/extension-guides/webview#theming-webview-content).
#### Misc
- [Every command](https://code.visualstudio.com/api/references/commands) built-in to VSCode - not used often, but here for reference.
- Note: VSCode's repo is the source code for the Monaco editor! An "editor" is a Monaco editor, and it shares the code for ITextModel, etc.
#### VSCode's Extension API
Void is no longer an extension, so these links are no longer required, but they might be useful if we ever build an extension again.
- [Files you need in an extension](https://code.visualstudio.com/api/get-started/extension-anatomy).
- [An extension's `package.json` schema](https://code.visualstudio.com/api/references/extension-manifest).
- ["Contributes" Guide](https://code.visualstudio.com/api/references/contribution-points) - the `"contributes"` part of `package.json` is how an extension mounts.
- [The Full VSCode Extension API](https://code.visualstudio.com/api/references/vscode-api) - look on the right side for organization. The [bottom](https://code.visualstudio.com/api/references/vscode-api#api-patterns) of the page is easy to miss but is useful - cancellation tokens, events, disposables.
- [Activation events](https://code.visualstudio.com/api/references/activation-events) you can define in `package.json` (not the most useful).
================================================
FILE: build/.cachesalt
================================================
2024-12-11T00:28:56.838Z
================================================
FILE: build/.gitattributes
================================================
* text eol=lf
*.exe binary
*.dll binary
================================================
FILE: build/.gitignore
================================================
*.js.map
================================================
FILE: build/.moduleignore
================================================
# cleanup rules for node modules, .gitignore style
# native node modules
nan/**
*/node_modules/nan/**
fsevents/binding.gyp
fsevents/fsevents.cc
fsevents/build/**
fsevents/src/**
fsevents/test/**
!fsevents/**/*.node
@vscode/spdlog/binding.gyp
@vscode/spdlog/build/**
@vscode/spdlog/deps/**
@vscode/spdlog/src/**
@vscode/spdlog/test/**
@vscode/spdlog/*.yml
!@vscode/spdlog/build/Release/*.node
@vscode/deviceid/binding.gyp
@vscode/deviceid/build/**
@vscode/deviceid/deps/**
@vscode/deviceid/src/**
@vscode/deviceid/test/**
@vscode/deviceid/*.yml
!@vscode/deviceid/build/Release/*.node
@vscode/sqlite3/binding.gyp
@vscode/sqlite3/benchmark/**
@vscode/sqlite3/cloudformation/**
@vscode/sqlite3/deps/**
@vscode/sqlite3/test/**
@vscode/sqlite3/build/**
@vscode/sqlite3/src/**
!@vscode/sqlite3/build/Release/*.node
@vscode/windows-mutex/binding.gyp
@vscode/windows-mutex/build/**
@vscode/windows-mutex/src/**
!@vscode/windows-mutex/**/*.node
@vscode/windows-process-tree/binding.gyp
@vscode/windows-process-tree/build/**
@vscode/windows-process-tree/src/**
@vscode/windows-process-tree/tsconfig.json
@vscode/windows-process-tree/tslint.json
!@vscode/windows-process-tree/**/*.node
@vscode/windows-registry/binding.gyp
@vscode/windows-registry/src/**
@vscode/windows-registry/build/**
!@vscode/windows-registry/build/Release/*.node
@vscode/tree-sitter-wasm/wasm/tree-sitter-*.wasm
!@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm
!@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
native-keymap/binding.gyp
native-keymap/build/**
native-keymap/src/**
native-keymap/deps/**
!native-keymap/build/Release/*.node
native-is-elevated/binding.gyp
native-is-elevated/build/**
native-is-elevated/src/**
native-is-elevated/deps/**
!native-is-elevated/build/Release/*.node
native-watchdog/binding.gyp
native-watchdog/build/**
native-watchdog/src/**
!native-watchdog/build/Release/*.node
@vscode/vsce-sign/**
!@vscode/vsce-sign/src/main.d.ts
!@vscode/vsce-sign/src/main.js
!@vscode/vsce-sign/package.json
!@vscode/vsce-sign/bin/**
windows-foreground-love/binding.gyp
windows-foreground-love/build/**
windows-foreground-love/src/**
!windows-foreground-love/**/*.node
kerberos/binding.gyp
kerberos/build/**
kerberos/src/**
kerberos/node_modules/**
!kerberos/**/*.node
node-pty/binding.gyp
node-pty/build/**
node-pty/src/**
node-pty/lib/*.test.js
node-pty/tools/**
node-pty/deps/**
node-pty/scripts/**
node-pty/third_party/**
!node-pty/build/Release/spawn-helper
!node-pty/build/Release/*.exe
!node-pty/build/Release/*.dll
!node-pty/build/Release/*.node
!node-pty/build/Release/conpty/conpty.dll
!node-pty/build/Release/conpty/OpenConsole.exe
@parcel/watcher/binding.gyp
@parcel/watcher/build/**
@parcel/watcher/prebuilds/**
@parcel/watcher/src/**
!@parcel/watcher/build/Release/*.node
vsda/**
!vsda/index.js
!vsda/index.d.ts
!vsda/package.json
!vsda/build/Release/vsda.node
!vsda/rust/web/**
!vsda/rust/bundler/**
@vscode/policy-watcher/build/**
@vscode/policy-watcher/.husky/**
@vscode/policy-watcher/src/**
@vscode/policy-watcher/binding.gyp
@vscode/policy-watcher/README.md
@vscode/policy-watcher/index.d.ts
!@vscode/policy-watcher/build/Release/vscode-policy-watcher.node
@vscode/windows-ca-certs/**/*
!@vscode/windows-ca-certs/package.json
!@vscode/windows-ca-certs/**/*.node
@vscode/node-addon-api/**/*
node-addon-api/**/*
prebuild-install/**/*
# other node modules
**/docs/**
**/example/**
**/examples/**
**/test/**
**/tests/**
**/History.md
**/CHANGELOG.md
**/README.md
**/readme.md
**/readme.markdown
**/CODE_OF_CONDUCT.md
**/SUPPORT.md
**/CONTRIBUTING.md
**/*.ts
# Exclude TS files that aren't needed by TS extension
typescript/lib/tsc.js
typescript/lib/typescriptServices.js
typescript/lib/tsserverlibrary.js
# We still need to include stdlib d.ts
!typescript/lib/lib*.d.ts
jschardet/index.js
jschardet/src/**
jschardet/dist/jschardet.js
es6-promise/lib/**
vscode-textmate/webpack.config.js
zone.js/dist/**
!zone.js/dist/zone-node.js
# https://github.com/xtermjs/xterm.js/issues/3137
@xterm/xterm/src/**
@xterm/xterm/tsconfig.all.json
# https://github.com/xtermjs/xterm.js/issues/3138
@xterm/xterm-addon-*/src/**
@xterm/xterm-addon-*/fixtures/**
@xterm/xterm-addon-*/out/**
@xterm/xterm-addon-*/out-test/**
================================================
FILE: build/.moduleignore.darwin
================================================
@vscode/windows-mutex/index.js
@vscode/windows-mutex/**/*.node
@vscode/windows-mutex/*.md
@vscode/windows-mutex/package.json
@vscode/windows-process-tree/lib/**
@vscode/windows-process-tree/**/*.node
@vscode/windows-process-tree/LICENSE
@vscode/windows-process-tree/package.json
@vscode/windows-process-tree/*.md
@vscode/windows-registry/dist/**
@vscode/windows-registry/**/*.node
@vscode/windows-registry/*.md
@vscode/windows-registry/*.txt
@vscode/windows-registry/package.json
!@vscode/windows-registry/dist/index.d.ts
================================================
FILE: build/.moduleignore.linux
================================================
@vscode/windows-mutex/index.js
@vscode/windows-mutex/**/*.node
@vscode/windows-mutex/*.md
@vscode/windows-mutex/package.json
@vscode/windows-process-tree/lib/**
@vscode/windows-process-tree/**/*.node
@vscode/windows-process-tree/LICENSE
@vscode/windows-process-tree/package.json
@vscode/windows-process-tree/*.md
@vscode/windows-registry/dist/**
@vscode/windows-registry/**/*.node
@vscode/windows-registry/*.md
@vscode/windows-registry/*.txt
@vscode/windows-registry/package.json
!@vscode/windows-registry/dist/index.d.ts
================================================
FILE: build/.moduleignore.win32
================================================
================================================
FILE: build/.npmrc
================================================
disturl="https://nodejs.org/dist"
runtime="node"
build_from_source="true"
legacy-peer-deps="true"
force_process_config="true"
timeout=180000
================================================
FILE: build/.webignore
================================================
# cleanup rules for web node modules, .gitignore style
**/*.txt
**/*.json
**/*.md
**/*.d.ts
**/*.js.map
**/LICENSE
**/CONTRIBUTORS
**/docs/**
**/example/**
**/examples/**
jschardet/index.js
jschardet/src/**
jschardet/dist/jschardet.js
vscode-textmate/webpack.config.js
@xterm/xterm/src/**
@xterm/addon-clipboard/src/**
@xterm/addon-clipboard/out/**
@xterm/addon-image/src/**
@xterm/addon-image/out/**
@xterm/addon-ligatures/src/**
@xterm/addon-ligatures/out/**
@xterm/addon-search/src/**
@xterm/addon-search/out/**
@xterm/addon-search/fixtures/**
@xterm/addon-unicode11/src/**
@xterm/addon-unicode11/out/**
@xterm/addon-webgl/src/**
@xterm/addon-webgl/out/**
# This makes sure the model is included in the package
!@vscode/vscode-languagedetection/model/**
!@vscode/tree-sitter-wasm/wasm/**
# Ensure only the required telemetry pieces are loaded in web to reduce bundle size
@microsoft/1ds-core-js/**
@microsoft/1ds-post-js/**
@microsoft/applicationinsights-core-js/**
@microsoft/applicationinsights-shims/**
!@microsoft/1ds-core-js/dist/ms.core.min.js
!@microsoft/1ds-core-js/bundle/ms.core.min.js
!@microsoft/1ds-post-js/dist/ms.post.min.js
!@microsoft/1ds-post-js/bundle/ms.post.min.js
!@microsoft/applicationinsights-core-js/browser/applicationinsights-core-js.min.js
!@microsoft/applicationinsights-shims/dist/umd/applicationinsights-shims.min.js
vsda/**
!vsda/rust/web/**
================================================
FILE: build/azure-pipelines/alpine/cli-build-alpine.yml
================================================
parameters:
- name: VSCODE_BUILD_ALPINE
type: boolean
default: false
- name: VSCODE_BUILD_ALPINE_ARM64
type: boolean
default: false
- name: VSCODE_QUALITY
type: string
- name: VSCODE_CHECK_ONLY
type: boolean
default: false
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../cli/cli-apply-patches.yml@self
- script: |
set -e
npm ci
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install build dependencies
- task: Npm@1
displayName: Download openssl prebuilt
inputs:
command: custom
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.11
customRegistry: useFeed
customFeed: "Monaco/openssl-prebuilt"
workingDir: $(Build.ArtifactStagingDirectory)
- script: |
set -e
mkdir $(Build.ArtifactStagingDirectory)/openssl
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.11.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
displayName: Extract openssl prebuilt
# inspired by: https://github.com/emk/rust-musl-builder/blob/main/Dockerfile
- bash: |
set -e
sudo apt-get update
sudo apt-get install -yq build-essential musl-dev musl-tools linux-libc-dev pkgconf xutils-dev lld
sudo ln -s "/usr/bin/g++" "/usr/bin/musl-g++" || echo "link exists"
displayName: Install musl build dependencies
- template: ../cli/install-rust-posix.yml@self
parameters:
targets:
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true) }}:
- aarch64-unknown-linux-musl
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE, true) }}:
- x86_64-unknown-linux-musl
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_CLI_TARGET: aarch64-unknown-linux-musl
VSCODE_CLI_ARTIFACT: vscode_cli_alpine_arm64_cli
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_ENV:
CXX_aarch64-unknown-linux-musl: musl-g++
CC_aarch64-unknown-linux-musl: musl-gcc
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-linux-musl/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-linux-musl/include
OPENSSL_STATIC: "1"
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_CLI_TARGET: x86_64-unknown-linux-musl
VSCODE_CLI_ARTIFACT: vscode_cli_alpine_x64_cli
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_ENV:
CXX_aarch64-unknown-linux-musl: musl-g++
CC_aarch64-unknown-linux-musl: musl-gcc
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-linux-musl/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-linux-musl/include
OPENSSL_STATIC: "1"
- ${{ if not(parameters.VSCODE_CHECK_ONLY) }}:
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/vscode_cli_alpine_arm64_cli.tar.gz
artifactName: vscode_cli_alpine_arm64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Alpine arm64 CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish vscode_cli_alpine_arm64_cli artifact
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/vscode_cli_alpine_x64_cli.tar.gz
artifactName: vscode_cli_alpine_x64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Alpine x64 CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish vscode_cli_alpine_x64_cli artifact
================================================
FILE: build/azure-pipelines/alpine/product-build-alpine.yml
================================================
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- task: DownloadPipelineArtifact@2
inputs:
artifact: Compilation
path: $(Build.ArtifactStagingDirectory)
displayName: Download compilation output
- script: tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
displayName: Extract compilation output
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js alpine $VSCODE_ARCH > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- script: tar -xzf .build/node_modules_cache/cache.tgz
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- task: Docker@1
inputs:
azureSubscriptionEndpoint: vscode
azureContainerRegistry: vscodehub.azurecr.io
command: "Run an image"
imageName: "vscode-linux-build-agent:alpine-$(VSCODE_ARCH)"
containerCommand: uname
displayName: "Pull image"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: sudo apt-get update && sudo apt-get install -y libkrb5-dev
displayName: Install build dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
env:
npm_config_arch: $(NPM_ARCH)
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
VSCODE_REMOTE_DEPENDENCIES_CONTAINER_NAME: vscodehub.azurecr.io/vscode-linux-build-agent:alpine-$(VSCODE_ARCH)
VSCODE_HOST_MOUNT: "/mnt/vss/_work/1/s"
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: node build/azure-pipelines/distro/mixin-npm
displayName: Mixin distro node modules
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: |
set -e
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
mkdir -p .build/node_modules_cache
tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- template: ../common/install-builtin-extensions.yml@self
- script: |
set -e
TARGET=$([ "$VSCODE_ARCH" == "x64" ] && echo "linux-alpine" || echo "alpine-arm64") # TODO@joaomoreno
npm run gulp vscode-reh-$TARGET-min-ci
(cd .. && mv vscode-reh-$TARGET vscode-server-$TARGET) # TODO@joaomoreno
ARCHIVE_PATH=".build/linux/server/vscode-server-$TARGET.tar.gz"
DIR_PATH="$(realpath ../vscode-server-$TARGET)"
mkdir -p $(dirname $ARCHIVE_PATH)
tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-server-$TARGET
echo "##vso[task.setvariable variable=SERVER_DIR_PATH]$DIR_PATH"
echo "##vso[task.setvariable variable=SERVER_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server
- script: |
set -e
TARGET=$([ "$VSCODE_ARCH" == "x64" ] && echo "linux-alpine" || echo "alpine-arm64")
npm run gulp vscode-reh-web-$TARGET-min-ci
(cd .. && mv vscode-reh-web-$TARGET vscode-server-$TARGET-web) # TODO@joaomoreno
ARCHIVE_PATH=".build/linux/web/vscode-server-$TARGET-web.tar.gz"
DIR_PATH="$(realpath ../vscode-server-$TARGET-web)"
mkdir -p $(dirname $ARCHIVE_PATH)
tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-server-$TARGET-web
echo "##vso[task.setvariable variable=WEB_DIR_PATH]$DIR_PATH"
echo "##vso[task.setvariable variable=WEB_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server (web)
- script: echo "##vso[task.setvariable variable=ARTIFACT_PREFIX]attempt$(System.JobAttempt)_"
condition: and(succeededOrFailed(), notIn(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues'))
displayName: Generate artifact prefix
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SERVER_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_server_alpine_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(SERVER_DIR_PATH)
sbomPackageName: "VS Code Alpine $(VSCODE_ARCH) Server"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish server archive
condition: and(succeededOrFailed(), ne(variables['SERVER_PATH'], ''), ne(variables['VSCODE_ARCH'], 'x64'))
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(WEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_web_alpine_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(WEB_DIR_PATH)
sbomPackageName: "VS Code Alpine $(VSCODE_ARCH) Web"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish web server archive
condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], ''), ne(variables['VSCODE_ARCH'], 'x64'))
# same as above, keep legacy name
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SERVER_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_server_linux_alpine_archive-unsigned
sbomEnabled: false
displayName: Publish x64 server archive
condition: and(succeededOrFailed(), ne(variables['SERVER_PATH'], ''), eq(variables['VSCODE_ARCH'], 'x64'))
# same as above, keep legacy name
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(WEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_web_linux_alpine_archive-unsigned
sbomEnabled: false
displayName: Publish x64 web server archive
condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], ''), eq(variables['VSCODE_ARCH'], 'x64'))
================================================
FILE: build/azure-pipelines/cli/cli-apply-patches.yml
================================================
steps:
- template: ../distro/download-distro.yml@self
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- script: node .build/distro/cli-patches/index.js
displayName: Apply distro patches
================================================
FILE: build/azure-pipelines/cli/cli-compile.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_CLI_TARGET
type: string
- name: VSCODE_CLI_ARTIFACT
type: string
- name: VSCODE_CLI_ENV
type: object
default: {}
- name: VSCODE_CHECK_ONLY
type: boolean
default: false
steps:
- ${{ if contains(parameters.VSCODE_CLI_TARGET, '-windows-') }}:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- pwsh: Write-Host "##vso[task.setvariable variable=VSCODE_CLI_PRODUCT_JSON]$(Build.SourcesDirectory)/product.json"
displayName: Set product.json path
- ${{ else }}:
- pwsh: Write-Host "##vso[task.setvariable variable=VSCODE_CLI_PRODUCT_JSON]$(Build.SourcesDirectory)/.build/distro/mixin/${{ parameters.VSCODE_QUALITY }}/product.json"
displayName: Set product.json path
- ${{ else }}:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: echo "##vso[task.setvariable variable=VSCODE_CLI_PRODUCT_JSON]$(Build.SourcesDirectory)/product.json"
displayName: Set product.json path
- ${{ else }}:
- script: echo "##vso[task.setvariable variable=VSCODE_CLI_PRODUCT_JSON]$(Build.SourcesDirectory)/.build/distro/mixin/${{ parameters.VSCODE_QUALITY }}/product.json"
displayName: Set product.json path
- ${{ if parameters.VSCODE_CHECK_ONLY }}:
- script: cargo clippy --target ${{ parameters.VSCODE_CLI_TARGET }} --bin=code
displayName: Lint ${{ parameters.VSCODE_CLI_TARGET }}
workingDirectory: $(Build.SourcesDirectory)/cli
env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
${{ each pair in parameters.VSCODE_CLI_ENV }}:
${{ pair.key }}: ${{ pair.value }}
- ${{ else }}:
- ${{ if contains(parameters.VSCODE_CLI_TARGET, '-linux-') }}:
- script: |
set -e
if [ -n "$SYSROOT_ARCH" ]; then
export VSCODE_SYSROOT_DIR=$(Build.SourcesDirectory)/.build/sysroots
node -e '(async () => { const { getVSCodeSysroot } = require("../build/linux/debian/install-sysroot.js"); await getVSCodeSysroot(process.env["SYSROOT_ARCH"]); })()'
if [ "$SYSROOT_ARCH" == "arm64" ]; then
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc"
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot"
export CC_aarch64_unknown_linux_gnu="$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc --sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot"
export PKG_CONFIG_LIBDIR_aarch64_unknown_linux_gnu="$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu/pkgconfig:$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/share/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR_aarch64_unknown_linux_gnu="$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot"
export OBJDUMP="$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/bin/objdump"
elif [ "$SYSROOT_ARCH" == "amd64" ]; then
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc"
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -C link-arg=-L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu"
export CC_x86_64_unknown_linux_gnu="$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc --sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot"
export PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu="$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu/pkgconfig:$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/share/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu="$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot"
export OBJDUMP="$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/bin/objdump"
elif [ "$SYSROOT_ARCH" == "armhf" ]; then
export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER="$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc"
export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUSTFLAGS="-C link-arg=--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot"
export CC_armv7_unknown_linux_gnueabihf="$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc --sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot"
export PKG_CONFIG_LIBDIR_armv7_unknown_linux_gnueabihf="$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/usr/lib/arm-rpi-linux-gnueabihf/pkgconfig:$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/usr/share/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR_armv7_unknown_linux_gnueabihf="$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot"
export OBJDUMP="$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/bin/objdump"
fi
fi
cargo build --release --target ${{ parameters.VSCODE_CLI_TARGET }} --bin=code
# verify glibc requirement
if [ -n "$SYSROOT_ARCH" ]; then
glibc_version="2.28"
while IFS= read -r line; do
if [[ $line == *"GLIBC_"* ]]; then
version=$(echo "$line" | awk '{print $5}' | tr -d '()')
version=${version#*_}
if [[ $(printf "%s\n%s" "$version" "$glibc_version" | sort -V | tail -n1) == "$version" ]]; then
glibc_version=$version
fi
fi
done < <("$OBJDUMP" -T "$PWD/target/${{ parameters.VSCODE_CLI_TARGET }}/release/code")
if [[ "$glibc_version" != "2.28" ]]; then
echo "Error: binary has dependency on GLIBC > 2.28, found $glibc_version"
exit 1
fi
fi
displayName: Compile ${{ parameters.VSCODE_CLI_TARGET }}
workingDirectory: $(Build.SourcesDirectory)/cli
env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
VSCODE_CLI_COMMIT: $(Build.SourceVersion)
GITHUB_TOKEN: "$(github-distro-mixin-password)"
${{ each pair in parameters.VSCODE_CLI_ENV }}:
${{ pair.key }}: ${{ pair.value }}
- ${{ else }}:
- script: cargo build --release --target ${{ parameters.VSCODE_CLI_TARGET }} --bin=code
displayName: Compile ${{ parameters.VSCODE_CLI_TARGET }}
workingDirectory: $(Build.SourcesDirectory)/cli
env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
VSCODE_CLI_COMMIT: $(Build.SourceVersion)
${{ each pair in parameters.VSCODE_CLI_ENV }}:
${{ pair.key }}: ${{ pair.value }}
- ${{ if contains(parameters.VSCODE_CLI_TARGET, '-windows-') }}:
- task: PublishSymbols@2
inputs:
IndexSources: false
SymbolsFolder: $(Build.SourcesDirectory)/cli/target/${{ parameters.VSCODE_CLI_TARGET }}/release
SearchPattern: 'code.pdb'
SymbolServerType: TeamServices
SymbolsProduct: 'code'
ArtifactServices.Symbol.AccountName: microsoft
ArtifactServices.Symbol.PAT: $(System.AccessToken)
ArtifactServices.Symbol.UseAAD: false
displayName: Publish Symbols
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$AppProductJson = Get-Content -Raw -Path "$env:VSCODE_CLI_PRODUCT_JSON" | ConvertFrom-Json
$env:VSCODE_CLI_APPLICATION_NAME = $AppProductJson.applicationName
Write-Host "##vso[task.setvariable variable=VSCODE_CLI_APPLICATION_NAME]$env:VSCODE_CLI_APPLICATION_NAME"
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)/cli"
Move-Item -Path $(Build.SourcesDirectory)/cli/target/${{ parameters.VSCODE_CLI_TARGET }}/release/code.exe -Destination "$(Build.ArtifactStagingDirectory)/cli/${env:VSCODE_CLI_APPLICATION_NAME}.exe"
displayName: Stage CLI
- task: ArchiveFiles@2
displayName: Archive CLI
inputs:
rootFolderOrFile: $(Build.ArtifactStagingDirectory)/cli/$(VSCODE_CLI_APPLICATION_NAME).exe
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/${{ parameters.VSCODE_CLI_ARTIFACT }}.zip
- ${{ else }}:
- script: |
set -e
VSCODE_CLI_APPLICATION_NAME=$(node -p "require(\"$VSCODE_CLI_PRODUCT_JSON\").applicationName")
echo "##vso[task.setvariable variable=VSCODE_CLI_APPLICATION_NAME]$VSCODE_CLI_APPLICATION_NAME"
mkdir -p $(Build.ArtifactStagingDirectory)/cli
mv $(Build.SourcesDirectory)/cli/target/${{ parameters.VSCODE_CLI_TARGET }}/release/code $(Build.ArtifactStagingDirectory)/cli/$VSCODE_CLI_APPLICATION_NAME
displayName: Stage CLI
- task: ArchiveFiles@2
displayName: Archive CLI
inputs:
rootFolderOrFile: $(Build.ArtifactStagingDirectory)/cli/$(VSCODE_CLI_APPLICATION_NAME)
includeRootFolder: false
${{ if contains(parameters.VSCODE_CLI_TARGET, '-darwin') }}:
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/${{ parameters.VSCODE_CLI_ARTIFACT }}.zip
${{ else }}:
archiveType: tar
tarCompression: gz
archiveFile: $(Build.ArtifactStagingDirectory)/${{ parameters.VSCODE_CLI_ARTIFACT }}.tar.gz
================================================
FILE: build/azure-pipelines/cli/cli-darwin-sign.yml
================================================
parameters:
- name: VSCODE_CLI_ARTIFACTS
type: object
default: []
steps:
- task: UseDotNet@2
inputs:
version: 6.x
- task: EsrpCodeSigning@5
inputs:
UseMSIAuthentication: true
ConnectedServiceName: vscode-esrp
AppRegistrationClientId: $(ESRP_CLIENT_ID)
AppRegistrationTenantId: $(ESRP_TENANT_ID)
AuthAKVName: vscode-esrp
AuthSignCertName: esrp-sign
FolderPath: .
Pattern: noop
displayName: 'Install ESRP Tooling'
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
- task: DownloadPipelineArtifact@2
displayName: Download ${{ target }}
inputs:
artifact: ${{ target }}
path: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}
- task: ExtractFiles@1
displayName: Extract artifact
inputs:
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/*.zip
destinationFolder: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll sign-darwin $(Build.ArtifactStagingDirectory)/pkg "*.zip"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll notarize-darwin $(Build.ArtifactStagingDirectory)/pkg "*.zip"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Notarize
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
- script: |
set -e
ASSET_ID=$(echo "${{ target }}" | sed "s/unsigned_//")
mv $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/${{ target }}.zip $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/$ASSET_ID.zip
echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID"
displayName: Set asset id variable
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/$(ASSET_ID).zip
artifactName: $(ASSET_ID)
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
sbomPackageName: "VS Code macOS ${{ target }} CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish signed artifact with ID $(ASSET_ID)
================================================
FILE: build/azure-pipelines/cli/cli-win32-sign.yml
================================================
parameters:
- name: VSCODE_CLI_ARTIFACTS
type: object
default: []
steps:
- task: UseDotNet@2
inputs:
version: 6.x
- task: EsrpCodeSigning@5
inputs:
UseMSIAuthentication: true
ConnectedServiceName: vscode-esrp
AppRegistrationClientId: $(ESRP_CLIENT_ID)
AppRegistrationTenantId: $(ESRP_TENANT_ID)
AuthAKVName: vscode-esrp
AuthSignCertName: esrp-sign
FolderPath: .
Pattern: noop
displayName: 'Install ESRP Tooling'
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$EsrpCodeSigningTool = (gci -directory -filter EsrpCodeSigning_* $(Agent.RootDirectory)\_tasks | Select-Object -last 1).FullName
$Version = (gci -directory $EsrpCodeSigningTool | Select-Object -last 1).FullName
echo "##vso[task.setvariable variable=EsrpCliDllPath]$Version\net6.0\esrpcli.dll"
displayName: Find ESRP CLI
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
- task: DownloadPipelineArtifact@2
displayName: Download artifact
inputs:
artifact: ${{ target }}
path: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}
- task: ExtractFiles@1
displayName: Extract artifact
inputs:
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/*.zip
destinationFolder: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
- powershell: node build\azure-pipelines\common\sign $env:EsrpCliDllPath sign-windows $(Build.ArtifactStagingDirectory)/sign "*.exe"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
- powershell: |
$ASSET_ID = "${{ target }}".replace("unsigned_", "");
echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID"
displayName: Set asset id variable
- task: ArchiveFiles@2
displayName: Archive signed files
inputs:
rootFolderOrFile: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(ASSET_ID).zip
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/$(ASSET_ID).zip
artifactName: $(ASSET_ID)
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
sbomPackageName: "VS Code Windows ${{ target }} CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish signed artifact with ID $(ASSET_ID)
================================================
FILE: build/azure-pipelines/cli/install-rust-posix.yml
================================================
parameters:
- name: channel
type: string
default: 1.85
- name: targets
default: []
type: object
# Todo: use 1ES pipeline once extension is installed in ADO
steps:
- task: RustInstaller@1
inputs:
rustVersion: ms-${{ parameters.channel }}
cratesIoFeedOverride: $(CARGO_REGISTRY)
additionalTargets: ${{ join(' ', parameters.targets) }}
toolchainFeed: https://pkgs.dev.azure.com/monacotools/Monaco/_packaging/vscode/nuget/v3/index.json
default: true
addToPath: true
displayName: Install MSFT Rust
condition: and(succeeded(), ne(variables['CARGO_REGISTRY'], 'none'))
- script: |
set -e
curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain $RUSTUP_TOOLCHAIN
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
env:
RUSTUP_TOOLCHAIN: ${{ parameters.channel }}
displayName: Install OSS Rust
condition: and(succeeded(), eq(variables['CARGO_REGISTRY'], 'none'))
- script: |
set -e
rustup default $RUSTUP_TOOLCHAIN
rustup update $RUSTUP_TOOLCHAIN
rustup component add clippy
env:
RUSTUP_TOOLCHAIN: ${{ parameters.channel }}
displayName: "Set Rust version"
condition: and(succeeded(), eq(variables['CARGO_REGISTRY'], 'none'))
- ${{ each target in parameters.targets }}:
- script: rustup target add ${{ target }}
displayName: "Adding Rust target '${{ target }}'"
condition: and(succeeded(), eq(variables['CARGO_REGISTRY'], 'none'))
- script: |
set -e
rustc --version
cargo --version
displayName: "Check Rust versions"
================================================
FILE: build/azure-pipelines/cli/install-rust-win32.yml
================================================
parameters:
- name: channel
type: string
default: 1.85
- name: targets
default: []
type: object
# Todo: use 1ES pipeline once extension is installed in ADO
steps:
- task: RustInstaller@1
inputs:
rustVersion: ms-${{ parameters.channel }}
cratesIoFeedOverride: $(CARGO_REGISTRY)
additionalTargets: ${{ join(' ', parameters.targets) }}
toolchainFeed: https://pkgs.dev.azure.com/monacotools/Monaco/_packaging/vscode/nuget/v3/index.json
default: true
addToPath: true
displayName: Install MSFT Rust
condition: and(succeeded(), ne(variables['CARGO_REGISTRY'], 'none'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
Invoke-WebRequest -Uri "https://win.rustup.rs" -Outfile $(Build.ArtifactStagingDirectory)/rustup-init.exe
exec { $(Build.ArtifactStagingDirectory)/rustup-init.exe -y --profile minimal --default-toolchain $env:RUSTUP_TOOLCHAIN --default-host x86_64-pc-windows-msvc }
echo "##vso[task.prependpath]$env:USERPROFILE\.cargo\bin"
env:
RUSTUP_TOOLCHAIN: ${{ parameters.channel }}
displayName: Install OSS Rust
condition: and(succeeded(), eq(variables['CARGO_REGISTRY'], 'none'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
exec { rustup default $RUSTUP_TOOLCHAIN }
exec { rustup update $RUSTUP_TOOLCHAIN }
env:
RUSTUP_TOOLCHAIN: ${{ parameters.channel }}
displayName: "Set Rust version"
condition: and(succeeded(), eq(variables['CARGO_REGISTRY'], 'none'))
- ${{ each target in parameters.targets }}:
- script: rustup target add ${{ target }}
displayName: "Adding Rust target '${{ target }}'"
condition: and(succeeded(), eq(variables['CARGO_REGISTRY'], 'none'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
exec { rustc --version }
exec { cargo --version }
displayName: "Check Rust versions"
================================================
FILE: build/azure-pipelines/cli/test.yml
================================================
steps:
- template: ./install-rust-posix.yml@self
- script: cargo clippy -- -D warnings
workingDirectory: cli
displayName: Clippy lint
- script: cargo test
workingDirectory: cli
displayName: Run unit tests
================================================
FILE: build/azure-pipelines/common/computeBuiltInDepsCacheKey.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const crypto_1 = __importDefault(require("crypto"));
const productjson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../../../product.json'), 'utf8'));
const shasum = crypto_1.default.createHash('sha256');
for (const ext of productjson.builtInExtensions) {
shasum.update(`${ext.name}@${ext.version}`);
}
process.stdout.write(shasum.digest('hex'));
//# sourceMappingURL=computeBuiltInDepsCacheKey.js.map
================================================
FILE: build/azure-pipelines/common/computeBuiltInDepsCacheKey.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../product.json'), 'utf8'));
const shasum = crypto.createHash('sha256');
for (const ext of productjson.builtInExtensions) {
shasum.update(`${ext.name}@${ext.version}`);
}
process.stdout.write(shasum.digest('hex'));
================================================
FILE: build/azure-pipelines/common/computeNodeModulesCacheKey.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const crypto_1 = __importDefault(require("crypto"));
const { dirs } = require('../../npm/dirs');
const ROOT = path_1.default.join(__dirname, '../../../');
const shasum = crypto_1.default.createHash('sha256');
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, 'build/.cachesalt')));
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, '.npmrc')));
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, 'build', '.npmrc')));
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, 'remote', '.npmrc')));
// Add `package.json` and `package-lock.json` files
for (const dir of dirs) {
const packageJsonPath = path_1.default.join(ROOT, dir, 'package.json');
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath).toString());
const relevantPackageJsonSections = {
dependencies: packageJson.dependencies,
devDependencies: packageJson.devDependencies,
optionalDependencies: packageJson.optionalDependencies,
resolutions: packageJson.resolutions,
distro: packageJson.distro
};
shasum.update(JSON.stringify(relevantPackageJsonSections));
const packageLockPath = path_1.default.join(ROOT, dir, 'package-lock.json');
shasum.update(fs_1.default.readFileSync(packageLockPath));
}
// Add any other command line arguments
for (let i = 2; i < process.argv.length; i++) {
shasum.update(process.argv[i]);
}
process.stdout.write(shasum.digest('hex'));
//# sourceMappingURL=computeNodeModulesCacheKey.js.map
================================================
FILE: build/azure-pipelines/common/computeNodeModulesCacheKey.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
const { dirs } = require('../../npm/dirs');
const ROOT = path.join(__dirname, '../../../');
const shasum = crypto.createHash('sha256');
shasum.update(fs.readFileSync(path.join(ROOT, 'build/.cachesalt')));
shasum.update(fs.readFileSync(path.join(ROOT, '.npmrc')));
shasum.update(fs.readFileSync(path.join(ROOT, 'build', '.npmrc')));
shasum.update(fs.readFileSync(path.join(ROOT, 'remote', '.npmrc')));
// Add `package.json` and `package-lock.json` files
for (const dir of dirs) {
const packageJsonPath = path.join(ROOT, dir, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
const relevantPackageJsonSections = {
dependencies: packageJson.dependencies,
devDependencies: packageJson.devDependencies,
optionalDependencies: packageJson.optionalDependencies,
resolutions: packageJson.resolutions,
distro: packageJson.distro
};
shasum.update(JSON.stringify(relevantPackageJsonSections));
const packageLockPath = path.join(ROOT, dir, 'package-lock.json');
shasum.update(fs.readFileSync(packageLockPath));
}
// Add any other command line arguments
for (let i = 2; i < process.argv.length; i++) {
shasum.update(process.argv[i]);
}
process.stdout.write(shasum.digest('hex'));
================================================
FILE: build/azure-pipelines/common/createBuild.js
================================================
"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 });
const identity_1 = require("@azure/identity");
const cosmos_1 = require("@azure/cosmos");
const retry_1 = require("./retry");
if (process.argv.length !== 3) {
console.error('Usage: node createBuild.js VERSION');
process.exit(-1);
}
function getEnv(name) {
const result = process.env[name];
if (typeof result === 'undefined') {
throw new Error('Missing env: ' + name);
}
return result;
}
async function main() {
const [, , _version] = process.argv;
const quality = getEnv('VSCODE_QUALITY');
const commit = getEnv('BUILD_SOURCEVERSION');
const queuedBy = getEnv('BUILD_QUEUEDBY');
const sourceBranch = getEnv('BUILD_SOURCEBRANCH');
const version = _version + (quality === 'stable' ? '' : `-${quality}`);
console.log('Creating build...');
console.log('Quality:', quality);
console.log('Version:', version);
console.log('Commit:', commit);
const build = {
id: commit,
timestamp: (new Date()).getTime(),
version,
isReleased: false,
private: process.env['VSCODE_PRIVATE_BUILD']?.toLowerCase() === 'true',
sourceBranch,
queuedBy,
assets: [],
updates: {}
};
const aadCredentials = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN']));
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
const scripts = client.database('builds').container(quality).scripts;
await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
}
main().then(() => {
console.log('Build successfully created');
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=createBuild.js.map
================================================
FILE: build/azure-pipelines/common/createBuild.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ClientAssertionCredential } from '@azure/identity';
import { CosmosClient } from '@azure/cosmos';
import { retry } from './retry';
if (process.argv.length !== 3) {
console.error('Usage: node createBuild.js VERSION');
process.exit(-1);
}
function getEnv(name: string): string {
const result = process.env[name];
if (typeof result === 'undefined') {
throw new Error('Missing env: ' + name);
}
return result;
}
async function main(): Promise {
const [, , _version] = process.argv;
const quality = getEnv('VSCODE_QUALITY');
const commit = getEnv('BUILD_SOURCEVERSION');
const queuedBy = getEnv('BUILD_QUEUEDBY');
const sourceBranch = getEnv('BUILD_SOURCEBRANCH');
const version = _version + (quality === 'stable' ? '' : `-${quality}`);
console.log('Creating build...');
console.log('Quality:', quality);
console.log('Version:', version);
console.log('Commit:', commit);
const build = {
id: commit,
timestamp: (new Date()).getTime(),
version,
isReleased: false,
private: process.env['VSCODE_PRIVATE_BUILD']?.toLowerCase() === 'true',
sourceBranch,
queuedBy,
assets: [],
updates: {}
};
const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!));
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
const scripts = client.database('builds').container(quality).scripts;
await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
}
main().then(() => {
console.log('Build successfully created');
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
================================================
FILE: build/azure-pipelines/common/extract-telemetry.sh
================================================
#!/usr/bin/env bash
set -e
cd $BUILD_STAGINGDIRECTORY
mkdir extraction
cd extraction
git clone --depth 1 https://github.com/microsoft/vscode-extension-telemetry.git
git clone --depth 1 https://github.com/microsoft/vscode-chrome-debug-core.git
git clone --depth 1 https://github.com/microsoft/vscode-node-debug2.git
git clone --depth 1 https://github.com/microsoft/vscode-node-debug.git
git clone --depth 1 https://github.com/microsoft/vscode-html-languageservice.git
git clone --depth 1 https://github.com/microsoft/vscode-json-languageservice.git
node $BUILD_SOURCESDIRECTORY/node_modules/.bin/vscode-telemetry-extractor --sourceDir $BUILD_SOURCESDIRECTORY --excludedDir $BUILD_SOURCESDIRECTORY/extensions --outputDir . --applyEndpoints
node $BUILD_SOURCESDIRECTORY/node_modules/.bin/vscode-telemetry-extractor --config $BUILD_SOURCESDIRECTORY/build/azure-pipelines/common/telemetry-config.json -o .
mkdir -p $BUILD_SOURCESDIRECTORY/.build/telemetry
mv declarations-resolved.json $BUILD_SOURCESDIRECTORY/.build/telemetry/telemetry-core.json
mv config-resolved.json $BUILD_SOURCESDIRECTORY/.build/telemetry/telemetry-extensions.json
cd ..
rm -rf extraction
================================================
FILE: build/azure-pipelines/common/getPublishAuthTokens.js
================================================
"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");
function e(name) {
const result = process.env[name];
if (typeof result !== 'string') {
throw new Error(`Missing env: ${name}`);
}
return result;
}
async function getAccessToken(endpoint, tenantId, clientId, idToken) {
const app = new msal_node_1.ConfidentialClientApplication({
auth: {
clientId,
authority: `https://login.microsoftonline.com/${tenantId}`,
clientAssertion: idToken
}
});
const result = await app.acquireTokenByClientCredential({ scopes: [`${endpoint}.default`] });
if (!result) {
throw new Error('Failed to get access token');
}
return {
token: result.accessToken,
expiresOnTimestamp: result.expiresOn.getTime(),
refreshAfterTimestamp: result.refreshOn?.getTime()
};
}
async function main() {
const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT'), e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_ID_TOKEN'));
const blobServiceAccessToken = await getAccessToken(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_ID_TOKEN']);
console.log(JSON.stringify({ cosmosDBAccessToken, blobServiceAccessToken }));
}
if (require.main === module) {
main().then(() => {
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
}
//# sourceMappingURL=getPublishAuthTokens.js.map
================================================
FILE: build/azure-pipelines/common/getPublishAuthTokens.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AccessToken } from '@azure/core-auth';
import { ConfidentialClientApplication } from '@azure/msal-node';
function e(name: string): string {
const result = process.env[name];
if (typeof result !== 'string') {
throw new Error(`Missing env: ${name}`);
}
return result;
}
export async function getAccessToken(endpoint: string, tenantId: string, clientId: string, idToken: string): Promise {
const app = new ConfidentialClientApplication({
auth: {
clientId,
authority: `https://login.microsoftonline.com/${tenantId}`,
clientAssertion: idToken
}
});
const result = await app.acquireTokenByClientCredential({ scopes: [`${endpoint}.default`] });
if (!result) {
throw new Error('Failed to get access token');
}
return {
token: result.accessToken,
expiresOnTimestamp: result.expiresOn!.getTime(),
refreshAfterTimestamp: result.refreshOn?.getTime()
};
}
async function main() {
const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT')!, e('AZURE_TENANT_ID')!, e('AZURE_CLIENT_ID')!, e('AZURE_ID_TOKEN')!);
const blobServiceAccessToken = await getAccessToken(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_ID_TOKEN']!);
console.log(JSON.stringify({ cosmosDBAccessToken, blobServiceAccessToken }));
}
if (require.main === module) {
main().then(() => {
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/azure-pipelines/common/install-builtin-extensions.yml
================================================
steps:
- pwsh: mkdir .build -ea 0
condition: and(succeeded(), contains(variables['Agent.OS'], 'windows'))
displayName: Create .build folder
- script: mkdir -p .build
condition: and(succeeded(), not(contains(variables['Agent.OS'], 'windows')))
displayName: Create .build folder
- script: node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
displayName: Prepare built-in extensions cache key
- task: Cache@2
inputs:
key: '"builtin-extensions" | .build/builtindepshash'
path: .build/builtInExtensions
cacheHitVar: BUILTIN_EXTENSIONS_RESTORED
displayName: Restore built-in extensions cache
- script: node build/lib/builtInExtensions.js
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
condition: and(succeeded(), ne(variables.BUILTIN_EXTENSIONS_RESTORED, 'true'))
displayName: Download built-in extensions
================================================
FILE: build/azure-pipelines/common/installPlaywright.js
================================================
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
process.env.DEBUG = 'pw:install'; // enable logging for this (https://github.com/microsoft/playwright/issues/17394)
const { installDefaultBrowsersForNpmInstall } = require('playwright-core/lib/server');
async function install() {
await installDefaultBrowsersForNpmInstall();
}
install();
//# sourceMappingURL=installPlaywright.js.map
================================================
FILE: build/azure-pipelines/common/listNodeModules.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
if (process.argv.length !== 3) {
console.error('Usage: node listNodeModules.js OUTPUT_FILE');
process.exit(-1);
}
const ROOT = path_1.default.join(__dirname, '../../../');
function findNodeModulesFiles(location, inNodeModules, result) {
const entries = fs_1.default.readdirSync(path_1.default.join(ROOT, location));
for (const entry of entries) {
const entryPath = `${location}/${entry}`;
if (/(^\/out)|(^\/src$)|(^\/.git$)|(^\/.build$)/.test(entryPath)) {
continue;
}
let stat;
try {
stat = fs_1.default.statSync(path_1.default.join(ROOT, entryPath));
}
catch (err) {
continue;
}
if (stat.isDirectory()) {
findNodeModulesFiles(entryPath, inNodeModules || (entry === 'node_modules'), result);
}
else {
if (inNodeModules) {
result.push(entryPath.substr(1));
}
}
}
}
const result = [];
findNodeModulesFiles('', false, result);
fs_1.default.writeFileSync(process.argv[2], result.join('\n') + '\n');
//# sourceMappingURL=listNodeModules.js.map
================================================
FILE: build/azure-pipelines/common/listNodeModules.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
if (process.argv.length !== 3) {
console.error('Usage: node listNodeModules.js OUTPUT_FILE');
process.exit(-1);
}
const ROOT = path.join(__dirname, '../../../');
function findNodeModulesFiles(location: string, inNodeModules: boolean, result: string[]) {
const entries = fs.readdirSync(path.join(ROOT, location));
for (const entry of entries) {
const entryPath = `${location}/${entry}`;
if (/(^\/out)|(^\/src$)|(^\/.git$)|(^\/.build$)/.test(entryPath)) {
continue;
}
let stat: fs.Stats;
try {
stat = fs.statSync(path.join(ROOT, entryPath));
} catch (err) {
continue;
}
if (stat.isDirectory()) {
findNodeModulesFiles(entryPath, inNodeModules || (entry === 'node_modules'), result);
} else {
if (inNodeModules) {
result.push(entryPath.substr(1));
}
}
}
}
const result: string[] = [];
findNodeModulesFiles('', false, result);
fs.writeFileSync(process.argv[2], result.join('\n') + '\n');
================================================
FILE: build/azure-pipelines/common/publish.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const stream_1 = require("stream");
const promises_1 = require("node:stream/promises");
const yauzl_1 = __importDefault(require("yauzl"));
const crypto_1 = __importDefault(require("crypto"));
const retry_1 = require("./retry");
const cosmos_1 = require("@azure/cosmos");
const child_process_1 = __importDefault(require("child_process"));
const os_1 = __importDefault(require("os"));
const node_worker_threads_1 = require("node:worker_threads");
const msal_node_1 = require("@azure/msal-node");
const storage_blob_1 = require("@azure/storage-blob");
const jws_1 = __importDefault(require("jws"));
const node_timers_1 = require("node:timers");
function e(name) {
const result = process.env[name];
if (typeof result !== 'string') {
throw new Error(`Missing env: ${name}`);
}
return result;
}
function hashStream(hashName, stream) {
return new Promise((c, e) => {
const shasum = crypto_1.default.createHash(hashName);
stream
.on('data', shasum.update.bind(shasum))
.on('error', e)
.on('close', () => c(shasum.digest()));
});
}
var StatusCode;
(function (StatusCode) {
StatusCode["Pass"] = "pass";
StatusCode["Aborted"] = "aborted";
StatusCode["Inprogress"] = "inprogress";
StatusCode["FailCanRetry"] = "failCanRetry";
StatusCode["FailDoNotRetry"] = "failDoNotRetry";
StatusCode["PendingAnalysis"] = "pendingAnalysis";
StatusCode["Cancelled"] = "cancelled";
})(StatusCode || (StatusCode = {}));
function getCertificateBuffer(input) {
return Buffer.from(input.replace(/-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----|\n/g, ''), 'base64');
}
function getThumbprint(input, algorithm) {
const buffer = getCertificateBuffer(input);
return crypto_1.default.createHash(algorithm).update(buffer).digest();
}
function getKeyFromPFX(pfx) {
const pfxCertificatePath = path_1.default.join(os_1.default.tmpdir(), 'cert.pfx');
const pemKeyPath = path_1.default.join(os_1.default.tmpdir(), 'key.pem');
try {
const pfxCertificate = Buffer.from(pfx, 'base64');
fs_1.default.writeFileSync(pfxCertificatePath, pfxCertificate);
child_process_1.default.execSync(`openssl pkcs12 -in "${pfxCertificatePath}" -nocerts -nodes -out "${pemKeyPath}" -passin pass:`);
const raw = fs_1.default.readFileSync(pemKeyPath, 'utf-8');
const result = raw.match(/-----BEGIN PRIVATE KEY-----[\s\S]+?-----END PRIVATE KEY-----/g)[0];
return result;
}
finally {
fs_1.default.rmSync(pfxCertificatePath, { force: true });
fs_1.default.rmSync(pemKeyPath, { force: true });
}
}
function getCertificatesFromPFX(pfx) {
const pfxCertificatePath = path_1.default.join(os_1.default.tmpdir(), 'cert.pfx');
const pemCertificatePath = path_1.default.join(os_1.default.tmpdir(), 'cert.pem');
try {
const pfxCertificate = Buffer.from(pfx, 'base64');
fs_1.default.writeFileSync(pfxCertificatePath, pfxCertificate);
child_process_1.default.execSync(`openssl pkcs12 -in "${pfxCertificatePath}" -nokeys -out "${pemCertificatePath}" -passin pass:`);
const raw = fs_1.default.readFileSync(pemCertificatePath, 'utf-8');
const matches = raw.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
return matches ? matches.reverse() : [];
}
finally {
fs_1.default.rmSync(pfxCertificatePath, { force: true });
fs_1.default.rmSync(pemCertificatePath, { force: true });
}
}
class ESRPReleaseService {
log;
clientId;
accessToken;
requestSigningCertificates;
requestSigningKey;
containerClient;
stagingSasToken;
static async create(log, tenantId, clientId, authCertificatePfx, requestSigningCertificatePfx, containerClient, stagingSasToken) {
const authKey = getKeyFromPFX(authCertificatePfx);
const authCertificate = getCertificatesFromPFX(authCertificatePfx)[0];
const requestSigningKey = getKeyFromPFX(requestSigningCertificatePfx);
const requestSigningCertificates = getCertificatesFromPFX(requestSigningCertificatePfx);
const app = new msal_node_1.ConfidentialClientApplication({
auth: {
clientId,
authority: `https://login.microsoftonline.com/${tenantId}`,
clientCertificate: {
thumbprintSha256: getThumbprint(authCertificate, 'sha256').toString('hex'),
privateKey: authKey,
x5c: authCertificate
}
}
});
const response = await app.acquireTokenByClientCredential({
scopes: ['https://api.esrp.microsoft.com/.default']
});
return new ESRPReleaseService(log, clientId, response.accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken);
}
static API_URL = 'https://api.esrp.microsoft.com/api/v3/releaseservices/clients/';
constructor(log, clientId, accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken) {
this.log = log;
this.clientId = clientId;
this.accessToken = accessToken;
this.requestSigningCertificates = requestSigningCertificates;
this.requestSigningKey = requestSigningKey;
this.containerClient = containerClient;
this.stagingSasToken = stagingSasToken;
}
async createRelease(version, filePath, friendlyFileName) {
const correlationId = crypto_1.default.randomUUID();
const blobClient = this.containerClient.getBlockBlobClient(correlationId);
this.log(`Uploading ${filePath} to ${blobClient.url}`);
await blobClient.uploadFile(filePath);
this.log('Uploaded blob successfully');
try {
this.log(`Submitting release for ${version}: ${filePath}`);
const submitReleaseResult = await this.submitRelease(version, filePath, friendlyFileName, correlationId, blobClient);
this.log(`Successfully submitted release ${submitReleaseResult.operationId}. Polling for completion...`);
// Poll every 5 seconds, wait 60 minutes max -> poll 60/5*60=720 times
for (let i = 0; i < 720; i++) {
await new Promise(c => setTimeout(c, 5000));
const releaseStatus = await this.getReleaseStatus(submitReleaseResult.operationId);
if (releaseStatus.status === 'pass') {
break;
}
else if (releaseStatus.status === 'aborted') {
this.log(JSON.stringify(releaseStatus));
throw new Error(`Release was aborted`);
}
else if (releaseStatus.status !== 'inprogress') {
this.log(JSON.stringify(releaseStatus));
throw new Error(`Unknown error when polling for release`);
}
}
const releaseDetails = await this.getReleaseDetails(submitReleaseResult.operationId);
if (releaseDetails.status !== 'pass') {
throw new Error(`Timed out waiting for release: ${JSON.stringify(releaseDetails)}`);
}
this.log('Successfully created release:', releaseDetails.files[0].fileDownloadDetails[0].downloadUrl);
return releaseDetails.files[0].fileDownloadDetails[0].downloadUrl;
}
finally {
this.log(`Deleting blob ${blobClient.url}`);
await blobClient.delete();
this.log('Deleted blob successfully');
}
}
async submitRelease(version, filePath, friendlyFileName, correlationId, blobClient) {
const size = fs_1.default.statSync(filePath).size;
const hash = await hashStream('sha256', fs_1.default.createReadStream(filePath));
const blobUrl = `${blobClient.url}?${this.stagingSasToken}`;
const message = {
customerCorrelationId: correlationId,
esrpCorrelationId: correlationId,
driEmail: ['joao.moreno@microsoft.com'],
createdBy: { userPrincipalName: 'jomo@microsoft.com' },
owners: [{ owner: { userPrincipalName: 'jomo@microsoft.com' } }],
approvers: [{ approver: { userPrincipalName: 'jomo@microsoft.com' }, isAutoApproved: true, isMandatory: false }],
releaseInfo: {
title: 'VS Code',
properties: {
'ReleaseContentType': 'InstallPackage'
},
minimumNumberOfApprovers: 1
},
productInfo: {
name: 'VS Code',
version,
description: 'VS Code'
},
accessPermissionsInfo: {
mainPublisher: 'VSCode',
channelDownloadEntityDetails: {
AllDownloadEntities: ['VSCode']
}
},
routingInfo: {
intent: 'filedownloadlinkgeneration'
},
files: [{
name: path_1.default.basename(filePath),
friendlyFileName,
tenantFileLocation: blobUrl,
tenantFileLocationType: 'AzureBlob',
sourceLocation: {
type: 'azureBlob',
blobUrl
},
hashType: 'sha256',
hash: Array.from(hash),
sizeInBytes: size
}]
};
message.jwsToken = await this.generateJwsToken(message);
const res = await fetch(`${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.accessToken}`
},
body: JSON.stringify(message)
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Failed to submit release: ${res.statusText}\n${text}`);
}
return await res.json();
}
async getReleaseStatus(releaseId) {
const url = `${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations/grs/${releaseId}`;
const res = await fetch(url, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
}
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Failed to get release status: ${res.statusText}\n${text}`);
}
return await res.json();
}
async getReleaseDetails(releaseId) {
const url = `${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations/grd/${releaseId}`;
const res = await fetch(url, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
}
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Failed to get release status: ${res.statusText}\n${text}`);
}
return await res.json();
}
async generateJwsToken(message) {
return jws_1.default.sign({
header: {
alg: 'RS256',
crit: ['exp', 'x5t'],
// Release service uses ticks, not seconds :roll_eyes: (https://stackoverflow.com/a/7968483)
exp: ((Date.now() + (6 * 60 * 1000)) * 10000) + 621355968000000000,
// Release service uses hex format, not base64url :roll_eyes:
x5t: getThumbprint(this.requestSigningCertificates[0], 'sha1').toString('hex'),
// Release service uses a '.' separated string, not an array of strings :roll_eyes:
x5c: this.requestSigningCertificates.map(c => getCertificateBuffer(c).toString('base64url')).join('.'),
},
payload: message,
privateKey: this.requestSigningKey,
});
}
}
class State {
statePath;
set = new Set();
constructor() {
const pipelineWorkspacePath = e('PIPELINE_WORKSPACE');
const previousState = fs_1.default.readdirSync(pipelineWorkspacePath)
.map(name => /^artifacts_processed_(\d+)$/.exec(name))
.filter((match) => !!match)
.map(match => ({ name: match[0], attempt: Number(match[1]) }))
.sort((a, b) => b.attempt - a.attempt)[0];
if (previousState) {
const previousStatePath = path_1.default.join(pipelineWorkspacePath, previousState.name, previousState.name + '.txt');
fs_1.default.readFileSync(previousStatePath, 'utf8').split(/\n/).filter(name => !!name).forEach(name => this.set.add(name));
}
const stageAttempt = e('SYSTEM_STAGEATTEMPT');
this.statePath = path_1.default.join(pipelineWorkspacePath, `artifacts_processed_${stageAttempt}`, `artifacts_processed_${stageAttempt}.txt`);
fs_1.default.mkdirSync(path_1.default.dirname(this.statePath), { recursive: true });
fs_1.default.writeFileSync(this.statePath, [...this.set.values()].map(name => `${name}\n`).join(''));
}
get size() {
return this.set.size;
}
has(name) {
return this.set.has(name);
}
add(name) {
this.set.add(name);
fs_1.default.appendFileSync(this.statePath, `${name}\n`);
}
[Symbol.iterator]() {
return this.set[Symbol.iterator]();
}
}
const azdoFetchOptions = {
headers: {
// Pretend we're a web browser to avoid download rate limits
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Referer': 'https://dev.azure.com',
Authorization: `Bearer ${e('SYSTEM_ACCESSTOKEN')}`
}
};
async function requestAZDOAPI(path) {
const abortController = new AbortController();
const timeout = setTimeout(() => abortController.abort(), 2 * 60 * 1000);
try {
const res = await fetch(`${e('BUILDS_API_URL')}${path}?api-version=6.0`, { ...azdoFetchOptions, signal: abortController.signal });
if (!res.ok) {
throw new Error(`Unexpected status code: ${res.status}`);
}
return await res.json();
}
finally {
clearTimeout(timeout);
}
}
async function getPipelineArtifacts() {
const result = await requestAZDOAPI('artifacts');
return result.value.filter(a => /^vscode_/.test(a.name) && !/sbom$/.test(a.name));
}
async function getPipelineTimeline() {
return await requestAZDOAPI('timeline');
}
async function downloadArtifact(artifact, downloadPath) {
const abortController = new AbortController();
const timeout = setTimeout(() => abortController.abort(), 4 * 60 * 1000);
try {
const res = await fetch(artifact.resource.downloadUrl, { ...azdoFetchOptions, signal: abortController.signal });
if (!res.ok) {
throw new Error(`Unexpected status code: ${res.status}`);
}
await (0, promises_1.pipeline)(stream_1.Readable.fromWeb(res.body), fs_1.default.createWriteStream(downloadPath));
}
finally {
clearTimeout(timeout);
}
}
async function unzip(packagePath, outputPath) {
return new Promise((resolve, reject) => {
yauzl_1.default.open(packagePath, { lazyEntries: true, autoClose: true }, (err, zipfile) => {
if (err) {
return reject(err);
}
const result = [];
zipfile.on('entry', entry => {
if (/\/$/.test(entry.fileName)) {
zipfile.readEntry();
}
else {
zipfile.openReadStream(entry, (err, istream) => {
if (err) {
return reject(err);
}
const filePath = path_1.default.join(outputPath, entry.fileName);
fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
const ostream = fs_1.default.createWriteStream(filePath);
ostream.on('finish', () => {
result.push(filePath);
zipfile.readEntry();
});
istream?.on('error', err => reject(err));
istream.pipe(ostream);
});
}
});
zipfile.on('close', () => resolve(result));
zipfile.readEntry();
});
});
}
// Contains all of the logic for mapping details to our actual product names in CosmosDB
function getPlatform(product, os, arch, type) {
switch (os) {
case 'win32':
switch (product) {
case 'client': {
switch (type) {
case 'archive':
return `win32-${arch}-archive`;
case 'setup':
return `win32-${arch}`;
case 'user-setup':
return `win32-${arch}-user`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
}
case 'server':
return `server-win32-${arch}`;
case 'web':
return `server-win32-${arch}-web`;
case 'cli':
return `cli-win32-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'alpine':
switch (product) {
case 'server':
return `server-alpine-${arch}`;
case 'web':
return `server-alpine-${arch}-web`;
case 'cli':
return `cli-alpine-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'linux':
switch (type) {
case 'snap':
return `linux-snap-${arch}`;
case 'archive-unsigned':
switch (product) {
case 'client':
return `linux-${arch}`;
case 'server':
return `server-linux-${arch}`;
case 'web':
if (arch === 'standalone') {
return 'web-standalone';
}
return `server-linux-${arch}-web`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'deb-package':
return `linux-deb-${arch}`;
case 'rpm-package':
return `linux-rpm-${arch}`;
case 'cli':
return `cli-linux-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'darwin':
switch (product) {
case 'client':
if (arch === 'x64') {
return 'darwin';
}
return `darwin-${arch}`;
case 'server':
if (arch === 'x64') {
return 'server-darwin';
}
return `server-darwin-${arch}`;
case 'web':
if (arch === 'x64') {
return 'server-darwin-web';
}
return `server-darwin-${arch}-web`;
case 'cli':
return `cli-darwin-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
}
// Contains all of the logic for mapping types to our actual types in CosmosDB
function getRealType(type) {
switch (type) {
case 'user-setup':
return 'setup';
case 'deb-package':
case 'rpm-package':
return 'package';
default:
return type;
}
}
async function withLease(client, fn) {
const lease = client.getBlobLeaseClient();
for (let i = 0; i < 360; i++) { // Try to get lease for 30 minutes
try {
await client.uploadData(new ArrayBuffer()); // blob needs to exist for lease to be acquired
await lease.acquireLease(60);
try {
const abortController = new AbortController();
const refresher = new Promise((c, e) => {
abortController.signal.onabort = () => {
(0, node_timers_1.clearInterval)(interval);
c();
};
const interval = (0, node_timers_1.setInterval)(() => {
lease.renewLease().catch(err => {
(0, node_timers_1.clearInterval)(interval);
e(new Error('Failed to renew lease ' + err));
});
}, 30_000);
});
const result = await Promise.race([fn(), refresher]);
abortController.abort();
return result;
}
finally {
await lease.releaseLease();
}
}
catch (err) {
if (err.statusCode !== 409 && err.statusCode !== 412) {
throw err;
}
await new Promise(c => setTimeout(c, 5000));
}
}
throw new Error('Failed to acquire lease on blob after 30 minutes');
}
async function processArtifact(artifact, filePath) {
const log = (...args) => console.log(`[${artifact.name}]`, ...args);
const match = /^vscode_(?[^_]+)_(?[^_]+)(?:_legacy)?_(?[^_]+)_(?[^_]+)$/.exec(artifact.name);
if (!match) {
throw new Error(`Invalid artifact name: ${artifact.name}`);
}
const { cosmosDBAccessToken, blobServiceAccessToken } = JSON.parse(e('PUBLISH_AUTH_TOKENS'));
const quality = e('VSCODE_QUALITY');
const version = e('BUILD_SOURCEVERSION');
const friendlyFileName = `${quality}/${version}/${path_1.default.basename(filePath)}`;
const blobServiceClient = new storage_blob_1.BlobServiceClient(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, { getToken: async () => blobServiceAccessToken });
const leasesContainerClient = blobServiceClient.getContainerClient('leases');
await leasesContainerClient.createIfNotExists();
const leaseBlobClient = leasesContainerClient.getBlockBlobClient(friendlyFileName);
log(`Acquiring lease for: ${friendlyFileName}`);
await withLease(leaseBlobClient, async () => {
log(`Successfully acquired lease for: ${friendlyFileName}`);
const url = `${e('PRSS_CDN_URL')}/${friendlyFileName}`;
const res = await (0, retry_1.retry)(() => fetch(url));
if (res.status === 200) {
log(`Already released and provisioned: ${url}`);
}
else {
const stagingContainerClient = blobServiceClient.getContainerClient('staging');
await stagingContainerClient.createIfNotExists();
const now = new Date().valueOf();
const oneHour = 60 * 60 * 1000;
const oneHourAgo = new Date(now - oneHour);
const oneHourFromNow = new Date(now + oneHour);
const userDelegationKey = await blobServiceClient.getUserDelegationKey(oneHourAgo, oneHourFromNow);
const sasOptions = { containerName: 'staging', permissions: storage_blob_1.ContainerSASPermissions.from({ read: true }), startsOn: oneHourAgo, expiresOn: oneHourFromNow };
const stagingSasToken = (0, storage_blob_1.generateBlobSASQueryParameters)(sasOptions, userDelegationKey, e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')).toString();
const releaseService = await ESRPReleaseService.create(log, e('RELEASE_TENANT_ID'), e('RELEASE_CLIENT_ID'), e('RELEASE_AUTH_CERT'), e('RELEASE_REQUEST_SIGNING_CERT'), stagingContainerClient, stagingSasToken);
await releaseService.createRelease(version, filePath, friendlyFileName);
}
const { product, os, arch, unprocessedType } = match.groups;
const platform = getPlatform(product, os, arch, unprocessedType);
const type = getRealType(unprocessedType);
const size = fs_1.default.statSync(filePath).size;
const stream = fs_1.default.createReadStream(filePath);
const [hash, sha256hash] = await Promise.all([hashStream('sha1', stream), hashStream('sha256', stream)]); // CodeQL [SM04514] Using SHA1 only for legacy reasons, we are actually only respecting SHA256
const asset = { platform, type, url, hash: hash.toString('hex'), sha256hash: sha256hash.toString('hex'), size, supportsFastUpdate: true };
log('Creating asset...');
const result = await (0, retry_1.retry)(async (attempt) => {
log(`Creating asset in Cosmos DB (attempt ${attempt})...`);
const client = new cosmos_1.CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), tokenProvider: () => Promise.resolve(`type=aad&ver=1.0&sig=${cosmosDBAccessToken.token}`) });
const scripts = client.database('builds').container(quality).scripts;
const { resource: result } = await scripts.storedProcedure('createAsset').execute('', [version, asset, true]);
return result;
});
if (result === 'already exists') {
log('Asset already exists!');
}
else {
log('Asset successfully created: ', JSON.stringify(asset, undefined, 2));
}
});
log(`Successfully released lease for: ${friendlyFileName}`);
}
// It is VERY important that we don't download artifacts too much too fast from AZDO.
// AZDO throttles us SEVERELY if we do. Not just that, but they also close open
// sockets, so the whole things turns to a grinding halt. So, downloading and extracting
// happens serially in the main thread, making the downloads are spaced out
// properly. For each extracted artifact, we spawn a worker thread to upload it to
// the CDN and finally update the build in Cosmos DB.
async function main() {
if (!node_worker_threads_1.isMainThread) {
const { artifact, artifactFilePath } = node_worker_threads_1.workerData;
await processArtifact(artifact, artifactFilePath);
return;
}
const done = new State();
const processing = new Set();
for (const name of done) {
console.log(`\u2705 ${name}`);
}
const stages = new Set(['Compile']);
if (e('VSCODE_BUILD_STAGE_LINUX') === 'True' ||
e('VSCODE_BUILD_STAGE_ALPINE') === 'True' ||
e('VSCODE_BUILD_STAGE_MACOS') === 'True' ||
e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') {
stages.add('CompileCLI');
}
if (e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') {
stages.add('Windows');
}
if (e('VSCODE_BUILD_STAGE_LINUX') === 'True') {
stages.add('Linux');
}
if (e('VSCODE_BUILD_STAGE_ALPINE') === 'True') {
stages.add('Alpine');
}
if (e('VSCODE_BUILD_STAGE_MACOS') === 'True') {
stages.add('macOS');
}
if (e('VSCODE_BUILD_STAGE_WEB') === 'True') {
stages.add('Web');
}
let resultPromise = Promise.resolve([]);
const operations = [];
while (true) {
const [timeline, artifacts] = await Promise.all([(0, retry_1.retry)(() => getPipelineTimeline()), (0, retry_1.retry)(() => getPipelineArtifacts())]);
const stagesCompleted = new Set(timeline.records.filter(r => r.type === 'Stage' && r.state === 'completed' && stages.has(r.name)).map(r => r.name));
const stagesInProgress = [...stages].filter(s => !stagesCompleted.has(s));
const artifactsInProgress = artifacts.filter(a => processing.has(a.name));
if (stagesInProgress.length === 0 && artifacts.length === done.size + processing.size) {
break;
}
else if (stagesInProgress.length > 0) {
console.log('Stages in progress:', stagesInProgress.join(', '));
}
else if (artifactsInProgress.length > 0) {
console.log('Artifacts in progress:', artifactsInProgress.map(a => a.name).join(', '));
}
else {
console.log(`Waiting for a total of ${artifacts.length}, ${done.size} done, ${processing.size} in progress...`);
}
for (const artifact of artifacts) {
if (done.has(artifact.name) || processing.has(artifact.name)) {
continue;
}
console.log(`[${artifact.name}] Found new artifact`);
const artifactZipPath = path_1.default.join(e('AGENT_TEMPDIRECTORY'), `${artifact.name}.zip`);
await (0, retry_1.retry)(async (attempt) => {
const start = Date.now();
console.log(`[${artifact.name}] Downloading (attempt ${attempt})...`);
await downloadArtifact(artifact, artifactZipPath);
const archiveSize = fs_1.default.statSync(artifactZipPath).size;
const downloadDurationS = (Date.now() - start) / 1000;
const downloadSpeedKBS = Math.round((archiveSize / 1024) / downloadDurationS);
console.log(`[${artifact.name}] Successfully downloaded after ${Math.floor(downloadDurationS)} seconds(${downloadSpeedKBS} KB/s).`);
});
const artifactFilePaths = await unzip(artifactZipPath, e('AGENT_TEMPDIRECTORY'));
const artifactFilePath = artifactFilePaths.filter(p => !/_manifest/.test(p))[0];
processing.add(artifact.name);
const promise = new Promise((resolve, reject) => {
const worker = new node_worker_threads_1.Worker(__filename, { workerData: { artifact, artifactFilePath } });
worker.on('error', reject);
worker.on('exit', code => {
if (code === 0) {
resolve();
}
else {
reject(new Error(`[${artifact.name}] Worker stopped with exit code ${code}`));
}
});
});
const operation = promise.then(() => {
processing.delete(artifact.name);
done.add(artifact.name);
console.log(`\u2705 ${artifact.name} `);
});
operations.push({ name: artifact.name, operation });
resultPromise = Promise.allSettled(operations.map(o => o.operation));
}
await new Promise(c => setTimeout(c, 10_000));
}
console.log(`Found all ${done.size + processing.size} artifacts, waiting for ${processing.size} artifacts to finish publishing...`);
const artifactsInProgress = operations.filter(o => processing.has(o.name));
if (artifactsInProgress.length > 0) {
console.log('Artifacts in progress:', artifactsInProgress.map(a => a.name).join(', '));
}
const results = await resultPromise;
for (let i = 0; i < operations.length; i++) {
const result = results[i];
if (result.status === 'rejected') {
console.error(`[${operations[i].name}]`, result.reason);
}
}
if (results.some(r => r.status === 'rejected')) {
throw new Error('Some artifacts failed to publish');
}
console.log(`All ${done.size} artifacts published!`);
}
if (require.main === module) {
main().then(() => {
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
}
//# sourceMappingURL=publish.js.map
================================================
FILE: build/azure-pipelines/common/publish.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import { Readable } from 'stream';
import type { ReadableStream } from 'stream/web';
import { pipeline } from 'node:stream/promises';
import yauzl from 'yauzl';
import crypto from 'crypto';
import { retry } from './retry';
import { CosmosClient } from '@azure/cosmos';
import cp from 'child_process';
import os from 'os';
import { Worker, isMainThread, workerData } from 'node:worker_threads';
import { ConfidentialClientApplication } from '@azure/msal-node';
import { BlobClient, BlobServiceClient, BlockBlobClient, ContainerClient, ContainerSASPermissions, generateBlobSASQueryParameters } from '@azure/storage-blob';
import jws from 'jws';
import { clearInterval, setInterval } from 'node:timers';
function e(name: string): string {
const result = process.env[name];
if (typeof result !== 'string') {
throw new Error(`Missing env: ${name}`);
}
return result;
}
function hashStream(hashName: string, stream: Readable): Promise {
return new Promise((c, e) => {
const shasum = crypto.createHash(hashName);
stream
.on('data', shasum.update.bind(shasum))
.on('error', e)
.on('close', () => c(shasum.digest()));
});
}
interface ReleaseSubmitResponse {
operationId: string;
esrpCorrelationId: string;
code?: string;
message?: string;
target?: string;
innerError?: any;
}
interface ReleaseActivityInfo {
activityId: string;
activityType: string;
name: string;
status: string;
errorCode: number;
errorMessages: string[];
beginTime?: Date;
endTime?: Date;
lastModifiedAt?: Date;
}
interface InnerServiceError {
code: string;
details: { [key: string]: string };
innerError?: InnerServiceError;
}
interface ReleaseError {
errorCode: number;
errorMessages: string[];
}
const enum StatusCode {
Pass = 'pass',
Aborted = 'aborted',
Inprogress = 'inprogress',
FailCanRetry = 'failCanRetry',
FailDoNotRetry = 'failDoNotRetry',
PendingAnalysis = 'pendingAnalysis',
Cancelled = 'cancelled'
}
interface ReleaseResultMessage {
activities: ReleaseActivityInfo[];
childWorkflowType: string;
clientId: string;
customerCorrelationId: string;
errorInfo: InnerServiceError;
groupId: string;
lastModifiedAt: Date;
operationId: string;
releaseError: ReleaseError;
requestSubmittedAt: Date;
routedRegion: string;
status: StatusCode;
totalFileCount: number;
totalReleaseSize: number;
version: string;
}
interface ReleaseFileInfo {
name?: string;
hash?: number[];
sourceLocation?: FileLocation;
sizeInBytes?: number;
hashType?: FileHashType;
fileId?: any;
distributionRelativePath?: string;
partNumber?: string;
friendlyFileName?: string;
tenantFileLocationType?: string;
tenantFileLocation?: string;
signedEngineeringCopyLocation?: string;
encryptedDistributionBlobLocation?: string;
preEncryptedDistributionBlobLocation?: string;
secondaryDistributionHashRequired?: boolean;
secondaryDistributionHashType?: FileHashType;
lastModifiedAt?: Date;
cultureCodes?: string[];
displayFileInDownloadCenter?: boolean;
isPrimaryFileInDownloadCenter?: boolean;
fileDownloadDetails?: FileDownloadDetails[];
}
interface ReleaseDetailsFileInfo extends ReleaseFileInfo { }
interface ReleaseDetailsMessage extends ReleaseResultMessage {
clusterRegion: string;
correlationVector: string;
releaseCompletedAt?: Date;
releaseInfo: ReleaseInfo;
productInfo: ProductInfo;
createdBy: UserInfo;
owners: OwnerInfo[];
accessPermissionsInfo: AccessPermissionsInfo;
files: ReleaseDetailsFileInfo[];
comments: string[];
cancellationReason: string;
downloadCenterInfo: DownloadCenterInfo;
}
interface ProductInfo {
name?: string;
version?: string;
description?: string;
}
interface ReleaseInfo {
title?: string;
minimumNumberOfApprovers: number;
properties?: { [key: string]: string };
isRevision?: boolean;
revisionNumber?: string;
}
type FileLocationType = 'azureBlob';
interface FileLocation {
type: FileLocationType;
blobUrl: string;
uncPath?: string;
url?: string;
}
type FileHashType = 'sha256' | 'sha1';
interface FileDownloadDetails {
portalName: string;
downloadUrl: string;
}
interface RoutingInfo {
intent?: string;
contentType?: string;
contentOrigin?: string;
productState?: string;
audience?: string;
}
interface ReleaseFileInfo {
name?: string;
hash?: number[];
sourceLocation?: FileLocation;
sizeInBytes?: number;
hashType?: FileHashType;
fileId?: any;
distributionRelativePath?: string;
partNumber?: string;
friendlyFileName?: string;
tenantFileLocationType?: string;
tenantFileLocation?: string;
signedEngineeringCopyLocation?: string;
encryptedDistributionBlobLocation?: string;
preEncryptedDistributionBlobLocation?: string;
secondaryDistributionHashRequired?: boolean;
secondaryDistributionHashType?: FileHashType;
lastModifiedAt?: Date;
cultureCodes?: string[];
displayFileInDownloadCenter?: boolean;
isPrimaryFileInDownloadCenter?: boolean;
fileDownloadDetails?: FileDownloadDetails[];
}
interface UserInfo {
userPrincipalName?: string;
}
interface OwnerInfo {
owner: UserInfo;
}
interface ApproverInfo {
approver: UserInfo;
isAutoApproved: boolean;
isMandatory: boolean;
}
interface AccessPermissionsInfo {
mainPublisher?: string;
releasePublishers?: string[];
channelDownloadEntityDetails?: { [key: string]: string[] };
}
interface DownloadCenterLocaleInfo {
cultureCode?: string;
downloadTitle?: string;
shortName?: string;
shortDescription?: string;
longDescription?: string;
instructions?: string;
additionalInfo?: string;
keywords?: string[];
version?: string;
relatedLinks?: { [key: string]: URL };
}
interface DownloadCenterInfo {
downloadCenterId: number;
publishToDownloadCenter?: boolean;
publishingGroup?: string;
operatingSystems?: string[];
relatedReleases?: string[];
kbNumbers?: string[];
sbNumbers?: string[];
locales?: DownloadCenterLocaleInfo[];
additionalProperties?: { [key: string]: string };
}
interface ReleaseRequestMessage {
driEmail: string[];
groupId?: string;
customerCorrelationId: string;
esrpCorrelationId: string;
contextData?: { [key: string]: string };
releaseInfo: ReleaseInfo;
productInfo: ProductInfo;
files: ReleaseFileInfo[];
routingInfo?: RoutingInfo;
createdBy: UserInfo;
owners: OwnerInfo[];
approvers: ApproverInfo[];
accessPermissionsInfo: AccessPermissionsInfo;
jwsToken?: string;
publisherId?: string;
downloadCenterInfo?: DownloadCenterInfo;
}
function getCertificateBuffer(input: string) {
return Buffer.from(input.replace(/-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----|\n/g, ''), 'base64');
}
function getThumbprint(input: string, algorithm: string): Buffer {
const buffer = getCertificateBuffer(input);
return crypto.createHash(algorithm).update(buffer).digest();
}
function getKeyFromPFX(pfx: string): string {
const pfxCertificatePath = path.join(os.tmpdir(), 'cert.pfx');
const pemKeyPath = path.join(os.tmpdir(), 'key.pem');
try {
const pfxCertificate = Buffer.from(pfx, 'base64');
fs.writeFileSync(pfxCertificatePath, pfxCertificate);
cp.execSync(`openssl pkcs12 -in "${pfxCertificatePath}" -nocerts -nodes -out "${pemKeyPath}" -passin pass:`);
const raw = fs.readFileSync(pemKeyPath, 'utf-8');
const result = raw.match(/-----BEGIN PRIVATE KEY-----[\s\S]+?-----END PRIVATE KEY-----/g)![0];
return result;
} finally {
fs.rmSync(pfxCertificatePath, { force: true });
fs.rmSync(pemKeyPath, { force: true });
}
}
function getCertificatesFromPFX(pfx: string): string[] {
const pfxCertificatePath = path.join(os.tmpdir(), 'cert.pfx');
const pemCertificatePath = path.join(os.tmpdir(), 'cert.pem');
try {
const pfxCertificate = Buffer.from(pfx, 'base64');
fs.writeFileSync(pfxCertificatePath, pfxCertificate);
cp.execSync(`openssl pkcs12 -in "${pfxCertificatePath}" -nokeys -out "${pemCertificatePath}" -passin pass:`);
const raw = fs.readFileSync(pemCertificatePath, 'utf-8');
const matches = raw.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
return matches ? matches.reverse() : [];
} finally {
fs.rmSync(pfxCertificatePath, { force: true });
fs.rmSync(pemCertificatePath, { force: true });
}
}
class ESRPReleaseService {
static async create(
log: (...args: any[]) => void,
tenantId: string,
clientId: string,
authCertificatePfx: string,
requestSigningCertificatePfx: string,
containerClient: ContainerClient,
stagingSasToken: string
) {
const authKey = getKeyFromPFX(authCertificatePfx);
const authCertificate = getCertificatesFromPFX(authCertificatePfx)[0];
const requestSigningKey = getKeyFromPFX(requestSigningCertificatePfx);
const requestSigningCertificates = getCertificatesFromPFX(requestSigningCertificatePfx);
const app = new ConfidentialClientApplication({
auth: {
clientId,
authority: `https://login.microsoftonline.com/${tenantId}`,
clientCertificate: {
thumbprintSha256: getThumbprint(authCertificate, 'sha256').toString('hex'),
privateKey: authKey,
x5c: authCertificate
}
}
});
const response = await app.acquireTokenByClientCredential({
scopes: ['https://api.esrp.microsoft.com/.default']
});
return new ESRPReleaseService(log, clientId, response!.accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken);
}
private static API_URL = 'https://api.esrp.microsoft.com/api/v3/releaseservices/clients/';
private constructor(
private readonly log: (...args: any[]) => void,
private readonly clientId: string,
private readonly accessToken: string,
private readonly requestSigningCertificates: string[],
private readonly requestSigningKey: string,
private readonly containerClient: ContainerClient,
private readonly stagingSasToken: string
) { }
async createRelease(version: string, filePath: string, friendlyFileName: string) {
const correlationId = crypto.randomUUID();
const blobClient = this.containerClient.getBlockBlobClient(correlationId);
this.log(`Uploading ${filePath} to ${blobClient.url}`);
await blobClient.uploadFile(filePath);
this.log('Uploaded blob successfully');
try {
this.log(`Submitting release for ${version}: ${filePath}`);
const submitReleaseResult = await this.submitRelease(version, filePath, friendlyFileName, correlationId, blobClient);
this.log(`Successfully submitted release ${submitReleaseResult.operationId}. Polling for completion...`);
// Poll every 5 seconds, wait 60 minutes max -> poll 60/5*60=720 times
for (let i = 0; i < 720; i++) {
await new Promise(c => setTimeout(c, 5000));
const releaseStatus = await this.getReleaseStatus(submitReleaseResult.operationId);
if (releaseStatus.status === 'pass') {
break;
} else if (releaseStatus.status === 'aborted') {
this.log(JSON.stringify(releaseStatus));
throw new Error(`Release was aborted`);
} else if (releaseStatus.status !== 'inprogress') {
this.log(JSON.stringify(releaseStatus));
throw new Error(`Unknown error when polling for release`);
}
}
const releaseDetails = await this.getReleaseDetails(submitReleaseResult.operationId);
if (releaseDetails.status !== 'pass') {
throw new Error(`Timed out waiting for release: ${JSON.stringify(releaseDetails)}`);
}
this.log('Successfully created release:', releaseDetails.files[0].fileDownloadDetails![0].downloadUrl);
return releaseDetails.files[0].fileDownloadDetails![0].downloadUrl;
} finally {
this.log(`Deleting blob ${blobClient.url}`);
await blobClient.delete();
this.log('Deleted blob successfully');
}
}
private async submitRelease(
version: string,
filePath: string,
friendlyFileName: string,
correlationId: string,
blobClient: BlobClient
): Promise {
const size = fs.statSync(filePath).size;
const hash = await hashStream('sha256', fs.createReadStream(filePath));
const blobUrl = `${blobClient.url}?${this.stagingSasToken}`;
const message: ReleaseRequestMessage = {
customerCorrelationId: correlationId,
esrpCorrelationId: correlationId,
driEmail: ['joao.moreno@microsoft.com'],
createdBy: { userPrincipalName: 'jomo@microsoft.com' },
owners: [{ owner: { userPrincipalName: 'jomo@microsoft.com' } }],
approvers: [{ approver: { userPrincipalName: 'jomo@microsoft.com' }, isAutoApproved: true, isMandatory: false }],
releaseInfo: {
title: 'VS Code',
properties: {
'ReleaseContentType': 'InstallPackage'
},
minimumNumberOfApprovers: 1
},
productInfo: {
name: 'VS Code',
version,
description: 'VS Code'
},
accessPermissionsInfo: {
mainPublisher: 'VSCode',
channelDownloadEntityDetails: {
AllDownloadEntities: ['VSCode']
}
},
routingInfo: {
intent: 'filedownloadlinkgeneration'
},
files: [{
name: path.basename(filePath),
friendlyFileName,
tenantFileLocation: blobUrl,
tenantFileLocationType: 'AzureBlob',
sourceLocation: {
type: 'azureBlob',
blobUrl
},
hashType: 'sha256',
hash: Array.from(hash),
sizeInBytes: size
}]
};
message.jwsToken = await this.generateJwsToken(message);
const res = await fetch(`${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.accessToken}`
},
body: JSON.stringify(message)
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Failed to submit release: ${res.statusText}\n${text}`);
}
return await res.json() as ReleaseSubmitResponse;
}
private async getReleaseStatus(releaseId: string): Promise {
const url = `${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations/grs/${releaseId}`;
const res = await fetch(url, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
}
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Failed to get release status: ${res.statusText}\n${text}`);
}
return await res.json() as ReleaseResultMessage;
}
private async getReleaseDetails(releaseId: string): Promise {
const url = `${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations/grd/${releaseId}`;
const res = await fetch(url, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
}
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Failed to get release status: ${res.statusText}\n${text}`);
}
return await res.json() as ReleaseDetailsMessage;
}
private async generateJwsToken(message: ReleaseRequestMessage): Promise {
return jws.sign({
header: {
alg: 'RS256',
crit: ['exp', 'x5t'],
// Release service uses ticks, not seconds :roll_eyes: (https://stackoverflow.com/a/7968483)
exp: ((Date.now() + (6 * 60 * 1000)) * 10000) + 621355968000000000,
// Release service uses hex format, not base64url :roll_eyes:
x5t: getThumbprint(this.requestSigningCertificates[0], 'sha1').toString('hex'),
// Release service uses a '.' separated string, not an array of strings :roll_eyes:
x5c: this.requestSigningCertificates.map(c => getCertificateBuffer(c).toString('base64url')).join('.') as any,
},
payload: message,
privateKey: this.requestSigningKey,
});
}
}
class State {
private statePath: string;
private set = new Set();
constructor() {
const pipelineWorkspacePath = e('PIPELINE_WORKSPACE');
const previousState = fs.readdirSync(pipelineWorkspacePath)
.map(name => /^artifacts_processed_(\d+)$/.exec(name))
.filter((match): match is RegExpExecArray => !!match)
.map(match => ({ name: match![0], attempt: Number(match![1]) }))
.sort((a, b) => b.attempt - a.attempt)[0];
if (previousState) {
const previousStatePath = path.join(pipelineWorkspacePath, previousState.name, previousState.name + '.txt');
fs.readFileSync(previousStatePath, 'utf8').split(/\n/).filter(name => !!name).forEach(name => this.set.add(name));
}
const stageAttempt = e('SYSTEM_STAGEATTEMPT');
this.statePath = path.join(pipelineWorkspacePath, `artifacts_processed_${stageAttempt}`, `artifacts_processed_${stageAttempt}.txt`);
fs.mkdirSync(path.dirname(this.statePath), { recursive: true });
fs.writeFileSync(this.statePath, [...this.set.values()].map(name => `${name}\n`).join(''));
}
get size(): number {
return this.set.size;
}
has(name: string): boolean {
return this.set.has(name);
}
add(name: string): void {
this.set.add(name);
fs.appendFileSync(this.statePath, `${name}\n`);
}
[Symbol.iterator](): IterableIterator {
return this.set[Symbol.iterator]();
}
}
const azdoFetchOptions = {
headers: {
// Pretend we're a web browser to avoid download rate limits
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Referer': 'https://dev.azure.com',
Authorization: `Bearer ${e('SYSTEM_ACCESSTOKEN')}`
}
};
async function requestAZDOAPI(path: string): Promise {
const abortController = new AbortController();
const timeout = setTimeout(() => abortController.abort(), 2 * 60 * 1000);
try {
const res = await fetch(`${e('BUILDS_API_URL')}${path}?api-version=6.0`, { ...azdoFetchOptions, signal: abortController.signal });
if (!res.ok) {
throw new Error(`Unexpected status code: ${res.status}`);
}
return await res.json();
} finally {
clearTimeout(timeout);
}
}
interface Artifact {
readonly name: string;
readonly resource: {
readonly downloadUrl: string;
readonly properties: {
readonly artifactsize: number;
};
};
}
async function getPipelineArtifacts(): Promise {
const result = await requestAZDOAPI<{ readonly value: Artifact[] }>('artifacts');
return result.value.filter(a => /^vscode_/.test(a.name) && !/sbom$/.test(a.name));
}
interface Timeline {
readonly records: {
readonly name: string;
readonly type: string;
readonly state: string;
}[];
}
async function getPipelineTimeline(): Promise {
return await requestAZDOAPI('timeline');
}
async function downloadArtifact(artifact: Artifact, downloadPath: string): Promise {
const abortController = new AbortController();
const timeout = setTimeout(() => abortController.abort(), 4 * 60 * 1000);
try {
const res = await fetch(artifact.resource.downloadUrl, { ...azdoFetchOptions, signal: abortController.signal });
if (!res.ok) {
throw new Error(`Unexpected status code: ${res.status}`);
}
await pipeline(Readable.fromWeb(res.body as ReadableStream), fs.createWriteStream(downloadPath));
} finally {
clearTimeout(timeout);
}
}
async function unzip(packagePath: string, outputPath: string): Promise {
return new Promise((resolve, reject) => {
yauzl.open(packagePath, { lazyEntries: true, autoClose: true }, (err, zipfile) => {
if (err) {
return reject(err);
}
const result: string[] = [];
zipfile!.on('entry', entry => {
if (/\/$/.test(entry.fileName)) {
zipfile!.readEntry();
} else {
zipfile!.openReadStream(entry, (err, istream) => {
if (err) {
return reject(err);
}
const filePath = path.join(outputPath, entry.fileName);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
const ostream = fs.createWriteStream(filePath);
ostream.on('finish', () => {
result.push(filePath);
zipfile!.readEntry();
});
istream?.on('error', err => reject(err));
istream!.pipe(ostream);
});
}
});
zipfile!.on('close', () => resolve(result));
zipfile!.readEntry();
});
});
}
interface Asset {
platform: string;
type: string;
url: string;
mooncakeUrl?: string;
prssUrl?: string;
hash: string;
sha256hash: string;
size: number;
supportsFastUpdate?: boolean;
}
// Contains all of the logic for mapping details to our actual product names in CosmosDB
function getPlatform(product: string, os: string, arch: string, type: string): string {
switch (os) {
case 'win32':
switch (product) {
case 'client': {
switch (type) {
case 'archive':
return `win32-${arch}-archive`;
case 'setup':
return `win32-${arch}`;
case 'user-setup':
return `win32-${arch}-user`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
}
case 'server':
return `server-win32-${arch}`;
case 'web':
return `server-win32-${arch}-web`;
case 'cli':
return `cli-win32-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'alpine':
switch (product) {
case 'server':
return `server-alpine-${arch}`;
case 'web':
return `server-alpine-${arch}-web`;
case 'cli':
return `cli-alpine-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'linux':
switch (type) {
case 'snap':
return `linux-snap-${arch}`;
case 'archive-unsigned':
switch (product) {
case 'client':
return `linux-${arch}`;
case 'server':
return `server-linux-${arch}`;
case 'web':
if (arch === 'standalone') {
return 'web-standalone';
}
return `server-linux-${arch}-web`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'deb-package':
return `linux-deb-${arch}`;
case 'rpm-package':
return `linux-rpm-${arch}`;
case 'cli':
return `cli-linux-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
case 'darwin':
switch (product) {
case 'client':
if (arch === 'x64') {
return 'darwin';
}
return `darwin-${arch}`;
case 'server':
if (arch === 'x64') {
return 'server-darwin';
}
return `server-darwin-${arch}`;
case 'web':
if (arch === 'x64') {
return 'server-darwin-web';
}
return `server-darwin-${arch}-web`;
case 'cli':
return `cli-darwin-${arch}`;
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
default:
throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`);
}
}
// Contains all of the logic for mapping types to our actual types in CosmosDB
function getRealType(type: string) {
switch (type) {
case 'user-setup':
return 'setup';
case 'deb-package':
case 'rpm-package':
return 'package';
default:
return type;
}
}
async function withLease(client: BlockBlobClient, fn: () => Promise) {
const lease = client.getBlobLeaseClient();
for (let i = 0; i < 360; i++) { // Try to get lease for 30 minutes
try {
await client.uploadData(new ArrayBuffer()); // blob needs to exist for lease to be acquired
await lease.acquireLease(60);
try {
const abortController = new AbortController();
const refresher = new Promise((c, e) => {
abortController.signal.onabort = () => {
clearInterval(interval);
c();
};
const interval = setInterval(() => {
lease.renewLease().catch(err => {
clearInterval(interval);
e(new Error('Failed to renew lease ' + err));
});
}, 30_000);
});
const result = await Promise.race([fn(), refresher]);
abortController.abort();
return result;
} finally {
await lease.releaseLease();
}
} catch (err) {
if (err.statusCode !== 409 && err.statusCode !== 412) {
throw err;
}
await new Promise(c => setTimeout(c, 5000));
}
}
throw new Error('Failed to acquire lease on blob after 30 minutes');
}
async function processArtifact(
artifact: Artifact,
filePath: string
) {
const log = (...args: any[]) => console.log(`[${artifact.name}]`, ...args);
const match = /^vscode_(?[^_]+)_(?[^_]+)(?:_legacy)?_(?[^_]+)_(?[^_]+)$/.exec(artifact.name);
if (!match) {
throw new Error(`Invalid artifact name: ${artifact.name}`);
}
const { cosmosDBAccessToken, blobServiceAccessToken } = JSON.parse(e('PUBLISH_AUTH_TOKENS'));
const quality = e('VSCODE_QUALITY');
const version = e('BUILD_SOURCEVERSION');
const friendlyFileName = `${quality}/${version}/${path.basename(filePath)}`;
const blobServiceClient = new BlobServiceClient(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, { getToken: async () => blobServiceAccessToken });
const leasesContainerClient = blobServiceClient.getContainerClient('leases');
await leasesContainerClient.createIfNotExists();
const leaseBlobClient = leasesContainerClient.getBlockBlobClient(friendlyFileName);
log(`Acquiring lease for: ${friendlyFileName}`);
await withLease(leaseBlobClient, async () => {
log(`Successfully acquired lease for: ${friendlyFileName}`);
const url = `${e('PRSS_CDN_URL')}/${friendlyFileName}`;
const res = await retry(() => fetch(url));
if (res.status === 200) {
log(`Already released and provisioned: ${url}`);
} else {
const stagingContainerClient = blobServiceClient.getContainerClient('staging');
await stagingContainerClient.createIfNotExists();
const now = new Date().valueOf();
const oneHour = 60 * 60 * 1000;
const oneHourAgo = new Date(now - oneHour);
const oneHourFromNow = new Date(now + oneHour);
const userDelegationKey = await blobServiceClient.getUserDelegationKey(oneHourAgo, oneHourFromNow);
const sasOptions = { containerName: 'staging', permissions: ContainerSASPermissions.from({ read: true }), startsOn: oneHourAgo, expiresOn: oneHourFromNow };
const stagingSasToken = generateBlobSASQueryParameters(sasOptions, userDelegationKey, e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')).toString();
const releaseService = await ESRPReleaseService.create(
log,
e('RELEASE_TENANT_ID'),
e('RELEASE_CLIENT_ID'),
e('RELEASE_AUTH_CERT'),
e('RELEASE_REQUEST_SIGNING_CERT'),
stagingContainerClient,
stagingSasToken
);
await releaseService.createRelease(version, filePath, friendlyFileName);
}
const { product, os, arch, unprocessedType } = match.groups!;
const platform = getPlatform(product, os, arch, unprocessedType);
const type = getRealType(unprocessedType);
const size = fs.statSync(filePath).size;
const stream = fs.createReadStream(filePath);
const [hash, sha256hash] = await Promise.all([hashStream('sha1', stream), hashStream('sha256', stream)]); // CodeQL [SM04514] Using SHA1 only for legacy reasons, we are actually only respecting SHA256
const asset: Asset = { platform, type, url, hash: hash.toString('hex'), sha256hash: sha256hash.toString('hex'), size, supportsFastUpdate: true };
log('Creating asset...');
const result = await retry(async (attempt) => {
log(`Creating asset in Cosmos DB (attempt ${attempt})...`);
const client = new CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT')!, tokenProvider: () => Promise.resolve(`type=aad&ver=1.0&sig=${cosmosDBAccessToken.token}`) });
const scripts = client.database('builds').container(quality).scripts;
const { resource: result } = await scripts.storedProcedure('createAsset').execute<'ok' | 'already exists'>('', [version, asset, true]);
return result;
});
if (result === 'already exists') {
log('Asset already exists!');
} else {
log('Asset successfully created: ', JSON.stringify(asset, undefined, 2));
}
});
log(`Successfully released lease for: ${friendlyFileName}`);
}
// It is VERY important that we don't download artifacts too much too fast from AZDO.
// AZDO throttles us SEVERELY if we do. Not just that, but they also close open
// sockets, so the whole things turns to a grinding halt. So, downloading and extracting
// happens serially in the main thread, making the downloads are spaced out
// properly. For each extracted artifact, we spawn a worker thread to upload it to
// the CDN and finally update the build in Cosmos DB.
async function main() {
if (!isMainThread) {
const { artifact, artifactFilePath } = workerData;
await processArtifact(artifact, artifactFilePath);
return;
}
const done = new State();
const processing = new Set();
for (const name of done) {
console.log(`\u2705 ${name}`);
}
const stages = new Set(['Compile']);
if (
e('VSCODE_BUILD_STAGE_LINUX') === 'True' ||
e('VSCODE_BUILD_STAGE_ALPINE') === 'True' ||
e('VSCODE_BUILD_STAGE_MACOS') === 'True' ||
e('VSCODE_BUILD_STAGE_WINDOWS') === 'True'
) {
stages.add('CompileCLI');
}
if (e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') { stages.add('Windows'); }
if (e('VSCODE_BUILD_STAGE_LINUX') === 'True') { stages.add('Linux'); }
if (e('VSCODE_BUILD_STAGE_ALPINE') === 'True') { stages.add('Alpine'); }
if (e('VSCODE_BUILD_STAGE_MACOS') === 'True') { stages.add('macOS'); }
if (e('VSCODE_BUILD_STAGE_WEB') === 'True') { stages.add('Web'); }
let resultPromise = Promise.resolve[]>([]);
const operations: { name: string; operation: Promise }[] = [];
while (true) {
const [timeline, artifacts] = await Promise.all([retry(() => getPipelineTimeline()), retry(() => getPipelineArtifacts())]);
const stagesCompleted = new Set(timeline.records.filter(r => r.type === 'Stage' && r.state === 'completed' && stages.has(r.name)).map(r => r.name));
const stagesInProgress = [...stages].filter(s => !stagesCompleted.has(s));
const artifactsInProgress = artifacts.filter(a => processing.has(a.name));
if (stagesInProgress.length === 0 && artifacts.length === done.size + processing.size) {
break;
} else if (stagesInProgress.length > 0) {
console.log('Stages in progress:', stagesInProgress.join(', '));
} else if (artifactsInProgress.length > 0) {
console.log('Artifacts in progress:', artifactsInProgress.map(a => a.name).join(', '));
} else {
console.log(`Waiting for a total of ${artifacts.length}, ${done.size} done, ${processing.size} in progress...`);
}
for (const artifact of artifacts) {
if (done.has(artifact.name) || processing.has(artifact.name)) {
continue;
}
console.log(`[${artifact.name}] Found new artifact`);
const artifactZipPath = path.join(e('AGENT_TEMPDIRECTORY'), `${artifact.name}.zip`);
await retry(async (attempt) => {
const start = Date.now();
console.log(`[${artifact.name}] Downloading (attempt ${attempt})...`);
await downloadArtifact(artifact, artifactZipPath);
const archiveSize = fs.statSync(artifactZipPath).size;
const downloadDurationS = (Date.now() - start) / 1000;
const downloadSpeedKBS = Math.round((archiveSize / 1024) / downloadDurationS);
console.log(`[${artifact.name}] Successfully downloaded after ${Math.floor(downloadDurationS)} seconds(${downloadSpeedKBS} KB/s).`);
});
const artifactFilePaths = await unzip(artifactZipPath, e('AGENT_TEMPDIRECTORY'));
const artifactFilePath = artifactFilePaths.filter(p => !/_manifest/.test(p))[0];
processing.add(artifact.name);
const promise = new Promise((resolve, reject) => {
const worker = new Worker(__filename, { workerData: { artifact, artifactFilePath } });
worker.on('error', reject);
worker.on('exit', code => {
if (code === 0) {
resolve();
} else {
reject(new Error(`[${artifact.name}] Worker stopped with exit code ${code}`));
}
});
});
const operation = promise.then(() => {
processing.delete(artifact.name);
done.add(artifact.name);
console.log(`\u2705 ${artifact.name} `);
});
operations.push({ name: artifact.name, operation });
resultPromise = Promise.allSettled(operations.map(o => o.operation));
}
await new Promise(c => setTimeout(c, 10_000));
}
console.log(`Found all ${done.size + processing.size} artifacts, waiting for ${processing.size} artifacts to finish publishing...`);
const artifactsInProgress = operations.filter(o => processing.has(o.name));
if (artifactsInProgress.length > 0) {
console.log('Artifacts in progress:', artifactsInProgress.map(a => a.name).join(', '));
}
const results = await resultPromise;
for (let i = 0; i < operations.length; i++) {
const result = results[i];
if (result.status === 'rejected') {
console.error(`[${operations[i].name}]`, result.reason);
}
}
if (results.some(r => r.status === 'rejected')) {
throw new Error('Some artifacts failed to publish');
}
console.log(`All ${done.size} artifacts published!`);
}
if (require.main === module) {
main().then(() => {
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/azure-pipelines/common/releaseBuild.js
================================================
"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 });
const identity_1 = require("@azure/identity");
const cosmos_1 = require("@azure/cosmos");
const retry_1 = require("./retry");
function getEnv(name) {
const result = process.env[name];
if (typeof result === 'undefined') {
throw new Error('Missing env: ' + name);
}
return result;
}
function createDefaultConfig(quality) {
return {
id: quality,
frozen: false
};
}
async function getConfig(client, quality) {
const query = `SELECT TOP 1 * FROM c WHERE c.id = "${quality}"`;
const res = await client.database('builds').container('config').items.query(query).fetchAll();
if (res.resources.length === 0) {
return createDefaultConfig(quality);
}
return res.resources[0];
}
async function main(force) {
const commit = getEnv('BUILD_SOURCEVERSION');
const quality = getEnv('VSCODE_QUALITY');
const aadCredentials = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN']));
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
if (!force) {
const config = await getConfig(client, quality);
console.log('Quality config:', config);
if (config.frozen) {
console.log(`Skipping release because quality ${quality} is frozen.`);
return;
}
}
console.log(`Releasing build ${commit}...`);
const scripts = client.database('builds').container(quality).scripts;
await (0, retry_1.retry)(() => scripts.storedProcedure('releaseBuild').execute('', [commit]));
}
const [, , force] = process.argv;
console.log(process.argv);
main(/^true$/i.test(force)).then(() => {
console.log('Build successfully released');
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=releaseBuild.js.map
================================================
FILE: build/azure-pipelines/common/releaseBuild.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ClientAssertionCredential } from '@azure/identity';
import { CosmosClient } from '@azure/cosmos';
import { retry } from './retry';
function getEnv(name: string): string {
const result = process.env[name];
if (typeof result === 'undefined') {
throw new Error('Missing env: ' + name);
}
return result;
}
interface Config {
id: string;
frozen: boolean;
}
function createDefaultConfig(quality: string): Config {
return {
id: quality,
frozen: false
};
}
async function getConfig(client: CosmosClient, quality: string): Promise {
const query = `SELECT TOP 1 * FROM c WHERE c.id = "${quality}"`;
const res = await client.database('builds').container('config').items.query(query).fetchAll();
if (res.resources.length === 0) {
return createDefaultConfig(quality);
}
return res.resources[0] as Config;
}
async function main(force: boolean): Promise {
const commit = getEnv('BUILD_SOURCEVERSION');
const quality = getEnv('VSCODE_QUALITY');
const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!));
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
if (!force) {
const config = await getConfig(client, quality);
console.log('Quality config:', config);
if (config.frozen) {
console.log(`Skipping release because quality ${quality} is frozen.`);
return;
}
}
console.log(`Releasing build ${commit}...`);
const scripts = client.database('builds').container(quality).scripts;
await retry(() => scripts.storedProcedure('releaseBuild').execute('', [commit]));
}
const [, , force] = process.argv;
console.log(process.argv);
main(/^true$/i.test(force)).then(() => {
console.log('Build successfully released');
process.exit(0);
}, err => {
console.error(err);
process.exit(1);
});
================================================
FILE: build/azure-pipelines/common/retry.js
================================================
"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.retry = retry;
async function retry(fn) {
let lastError;
for (let run = 1; run <= 10; run++) {
try {
return await fn(run);
}
catch (err) {
if (!/fetch failed|terminated|aborted|timeout|TimeoutError|Timeout Error|RestError|Client network socket disconnected|socket hang up|ECONNRESET|CredentialUnavailableError|endpoints_resolution_error|Audience validation failed|end of central directory record signature not found/i.test(err.message)) {
throw err;
}
lastError = err;
// maximum delay is 10th retry: ~3 seconds
const millis = Math.floor((Math.random() * 200) + (50 * Math.pow(1.5, run)));
await new Promise(c => setTimeout(c, millis));
}
}
console.error(`Too many retries, aborting.`);
throw lastError;
}
//# sourceMappingURL=retry.js.map
================================================
FILE: build/azure-pipelines/common/retry.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export async function retry(fn: (attempt: number) => Promise): Promise {
let lastError: Error | undefined;
for (let run = 1; run <= 10; run++) {
try {
return await fn(run);
} catch (err) {
if (!/fetch failed|terminated|aborted|timeout|TimeoutError|Timeout Error|RestError|Client network socket disconnected|socket hang up|ECONNRESET|CredentialUnavailableError|endpoints_resolution_error|Audience validation failed|end of central directory record signature not found/i.test(err.message)) {
throw err;
}
lastError = err;
// maximum delay is 10th retry: ~3 seconds
const millis = Math.floor((Math.random() * 200) + (50 * Math.pow(1.5, run)));
await new Promise(c => setTimeout(c, millis));
}
}
console.error(`Too many retries, aborting.`);
throw lastError;
}
================================================
FILE: build/azure-pipelines/common/sign-win32.js
================================================
"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 sign_1 = require("./sign");
const path_1 = __importDefault(require("path"));
(0, sign_1.main)([
process.env['EsrpCliDllPath'],
'sign-windows',
path_1.default.dirname(process.argv[2]),
path_1.default.basename(process.argv[2])
]);
//# sourceMappingURL=sign-win32.js.map
================================================
FILE: build/azure-pipelines/common/sign-win32.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { main } from './sign';
import path from 'path';
main([
process.env['EsrpCliDllPath']!,
'sign-windows',
path.dirname(process.argv[2]),
path.basename(process.argv[2])
]);
================================================
FILE: build/azure-pipelines/common/sign.js
================================================
"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;
const child_process_1 = __importDefault(require("child_process"));
const fs_1 = __importDefault(require("fs"));
const crypto_1 = __importDefault(require("crypto"));
const path_1 = __importDefault(require("path"));
const os_1 = __importDefault(require("os"));
class Temp {
_files = [];
tmpNameSync() {
const file = path_1.default.join(os_1.default.tmpdir(), crypto_1.default.randomBytes(20).toString('hex'));
this._files.push(file);
return file;
}
dispose() {
for (const file of this._files) {
try {
fs_1.default.unlinkSync(file);
}
catch (err) {
// noop
}
}
}
}
exports.Temp = Temp;
function getParams(type) {
switch (type) {
case 'sign-windows':
return [
{
keyCode: 'CP-230012',
operationSetCode: 'SigntoolSign',
parameters: [
{ parameterName: 'OpusName', parameterValue: 'VS Code' },
{ parameterName: 'OpusInfo', parameterValue: 'https://code.visualstudio.com/' },
{ parameterName: 'Append', parameterValue: '/as' },
{ parameterName: 'FileDigest', parameterValue: '/fd "SHA256"' },
{ parameterName: 'PageHash', parameterValue: '/NPH' },
{ parameterName: 'TimeStamp', parameterValue: '/tr "http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer" /td sha256' }
],
toolName: 'sign',
toolVersion: '1.0'
},
{
keyCode: 'CP-230012',
operationSetCode: 'SigntoolVerify',
parameters: [
{ parameterName: 'VerifyAll', parameterValue: '/all' }
],
toolName: 'sign',
toolVersion: '1.0'
}
];
case 'sign-windows-appx':
return [
{
keyCode: 'CP-229979',
operationSetCode: 'SigntoolSign',
parameters: [
{ parameterName: 'OpusName', parameterValue: 'VS Code' },
{ parameterName: 'OpusInfo', parameterValue: 'https://code.visualstudio.com/' },
{ parameterName: 'FileDigest', parameterValue: '/fd "SHA256"' },
{ parameterName: 'PageHash', parameterValue: '/NPH' },
{ parameterName: 'TimeStamp', parameterValue: '/tr "http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer" /td sha256' }
],
toolName: 'sign',
toolVersion: '1.0'
},
{
keyCode: 'CP-229979',
operationSetCode: 'SigntoolVerify',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}
];
case 'sign-pgp':
return [{
keyCode: 'CP-450779-Pgp',
operationSetCode: 'LinuxSign',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}];
case 'sign-darwin':
return [{
keyCode: 'CP-401337-Apple',
operationSetCode: 'MacAppDeveloperSign',
parameters: [{ parameterName: 'Hardening', parameterValue: '--options=runtime' }],
toolName: 'sign',
toolVersion: '1.0'
}];
case 'notarize-darwin':
return [{
keyCode: 'CP-401337-Apple',
operationSetCode: 'MacAppNotarize',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}];
case 'nuget':
return [{
keyCode: 'CP-401405',
operationSetCode: 'NuGetSign',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}, {
keyCode: 'CP-401405',
operationSetCode: 'NuGetVerify',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}];
default:
throw new Error(`Sign type ${type} not found`);
}
}
function main([esrpCliPath, type, folderPath, pattern]) {
const tmp = new Temp();
process.on('exit', () => tmp.dispose());
const key = crypto_1.default.randomBytes(32);
const iv = crypto_1.default.randomBytes(16);
const cipher = crypto_1.default.createCipheriv('aes-256-cbc', key, iv);
const encryptedToken = cipher.update(process.env['SYSTEM_ACCESSTOKEN'].trim(), 'utf8', 'hex') + cipher.final('hex');
const encryptionDetailsPath = tmp.tmpNameSync();
fs_1.default.writeFileSync(encryptionDetailsPath, JSON.stringify({ key: key.toString('hex'), iv: iv.toString('hex') }));
const encryptedTokenPath = tmp.tmpNameSync();
fs_1.default.writeFileSync(encryptedTokenPath, encryptedToken);
const patternPath = tmp.tmpNameSync();
fs_1.default.writeFileSync(patternPath, pattern);
const paramsPath = tmp.tmpNameSync();
fs_1.default.writeFileSync(paramsPath, JSON.stringify(getParams(type)));
const dotnetVersion = child_process_1.default.execSync('dotnet --version', { encoding: 'utf8' }).trim();
const adoTaskVersion = path_1.default.basename(path_1.default.dirname(path_1.default.dirname(esrpCliPath)));
const federatedTokenData = {
jobId: process.env['SYSTEM_JOBID'],
planId: process.env['SYSTEM_PLANID'],
projectId: process.env['SYSTEM_TEAMPROJECTID'],
hub: process.env['SYSTEM_HOSTTYPE'],
uri: process.env['SYSTEM_COLLECTIONURI'],
managedIdentityId: process.env['VSCODE_ESRP_CLIENT_ID'],
managedIdentityTenantId: process.env['VSCODE_ESRP_TENANT_ID'],
serviceConnectionId: process.env['VSCODE_ESRP_SERVICE_CONNECTION_ID'],
tempDirectory: os_1.default.tmpdir(),
systemAccessToken: encryptedTokenPath,
encryptionKey: encryptionDetailsPath
};
const args = [
esrpCliPath,
'vsts.sign',
'-a', process.env['ESRP_CLIENT_ID'],
'-d', process.env['ESRP_TENANT_ID'],
'-k', JSON.stringify({ akv: 'vscode-esrp' }),
'-z', JSON.stringify({ akv: 'vscode-esrp', cert: 'esrp-sign' }),
'-f', folderPath,
'-p', patternPath,
'-u', 'false',
'-x', 'regularSigning',
'-b', 'input.json',
'-l', 'AzSecPack_PublisherPolicyProd.xml',
'-y', 'inlineSignParams',
'-j', paramsPath,
'-c', '9997',
'-t', '120',
'-g', '10',
'-v', 'Tls12',
'-s', 'https://api.esrp.microsoft.com/api/v1',
'-m', '0',
'-o', 'Microsoft',
'-i', 'https://www.microsoft.com',
'-n', '5',
'-r', 'true',
'-w', dotnetVersion,
'-skipAdoReportAttachment', 'false',
'-pendingAnalysisWaitTimeoutMinutes', '5',
'-adoTaskVersion', adoTaskVersion,
'-resourceUri', 'https://msazurecloud.onmicrosoft.com/api.esrp.microsoft.com',
'-esrpClientId', process.env['ESRP_CLIENT_ID'],
'-useMSIAuthentication', 'true',
'-federatedTokenData', JSON.stringify(federatedTokenData)
];
try {
child_process_1.default.execFileSync('dotnet', args, { stdio: 'inherit' });
}
catch (err) {
console.error('ESRP failed');
console.error(err);
process.exit(1);
}
}
if (require.main === module) {
main(process.argv.slice(2));
process.exit(0);
}
//# sourceMappingURL=sign.js.map
================================================
FILE: build/azure-pipelines/common/sign.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import cp from 'child_process';
import fs from 'fs';
import crypto from 'crypto';
import path from 'path';
import os from 'os';
export class Temp {
private _files: string[] = [];
tmpNameSync(): string {
const file = path.join(os.tmpdir(), crypto.randomBytes(20).toString('hex'));
this._files.push(file);
return file;
}
dispose(): void {
for (const file of this._files) {
try {
fs.unlinkSync(file);
} catch (err) {
// noop
}
}
}
}
interface Params {
readonly keyCode: string;
readonly operationSetCode: string;
readonly parameters: {
readonly parameterName: string;
readonly parameterValue: string;
}[];
readonly toolName: string;
readonly toolVersion: string;
}
function getParams(type: string): Params[] {
switch (type) {
case 'sign-windows':
return [
{
keyCode: 'CP-230012',
operationSetCode: 'SigntoolSign',
parameters: [
{ parameterName: 'OpusName', parameterValue: 'VS Code' },
{ parameterName: 'OpusInfo', parameterValue: 'https://code.visualstudio.com/' },
{ parameterName: 'Append', parameterValue: '/as' },
{ parameterName: 'FileDigest', parameterValue: '/fd "SHA256"' },
{ parameterName: 'PageHash', parameterValue: '/NPH' },
{ parameterName: 'TimeStamp', parameterValue: '/tr "http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer" /td sha256' }
],
toolName: 'sign',
toolVersion: '1.0'
},
{
keyCode: 'CP-230012',
operationSetCode: 'SigntoolVerify',
parameters: [
{ parameterName: 'VerifyAll', parameterValue: '/all' }
],
toolName: 'sign',
toolVersion: '1.0'
}
];
case 'sign-windows-appx':
return [
{
keyCode: 'CP-229979',
operationSetCode: 'SigntoolSign',
parameters: [
{ parameterName: 'OpusName', parameterValue: 'VS Code' },
{ parameterName: 'OpusInfo', parameterValue: 'https://code.visualstudio.com/' },
{ parameterName: 'FileDigest', parameterValue: '/fd "SHA256"' },
{ parameterName: 'PageHash', parameterValue: '/NPH' },
{ parameterName: 'TimeStamp', parameterValue: '/tr "http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer" /td sha256' }
],
toolName: 'sign',
toolVersion: '1.0'
},
{
keyCode: 'CP-229979',
operationSetCode: 'SigntoolVerify',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}
];
case 'sign-pgp':
return [{
keyCode: 'CP-450779-Pgp',
operationSetCode: 'LinuxSign',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}];
case 'sign-darwin':
return [{
keyCode: 'CP-401337-Apple',
operationSetCode: 'MacAppDeveloperSign',
parameters: [{ parameterName: 'Hardening', parameterValue: '--options=runtime' }],
toolName: 'sign',
toolVersion: '1.0'
}];
case 'notarize-darwin':
return [{
keyCode: 'CP-401337-Apple',
operationSetCode: 'MacAppNotarize',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}];
case 'nuget':
return [{
keyCode: 'CP-401405',
operationSetCode: 'NuGetSign',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}, {
keyCode: 'CP-401405',
operationSetCode: 'NuGetVerify',
parameters: [],
toolName: 'sign',
toolVersion: '1.0'
}];
default:
throw new Error(`Sign type ${type} not found`);
}
}
export function main([esrpCliPath, type, folderPath, pattern]: string[]) {
const tmp = new Temp();
process.on('exit', () => tmp.dispose());
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const encryptedToken = cipher.update(process.env['SYSTEM_ACCESSTOKEN']!.trim(), 'utf8', 'hex') + cipher.final('hex');
const encryptionDetailsPath = tmp.tmpNameSync();
fs.writeFileSync(encryptionDetailsPath, JSON.stringify({ key: key.toString('hex'), iv: iv.toString('hex') }));
const encryptedTokenPath = tmp.tmpNameSync();
fs.writeFileSync(encryptedTokenPath, encryptedToken);
const patternPath = tmp.tmpNameSync();
fs.writeFileSync(patternPath, pattern);
const paramsPath = tmp.tmpNameSync();
fs.writeFileSync(paramsPath, JSON.stringify(getParams(type)));
const dotnetVersion = cp.execSync('dotnet --version', { encoding: 'utf8' }).trim();
const adoTaskVersion = path.basename(path.dirname(path.dirname(esrpCliPath)));
const federatedTokenData = {
jobId: process.env['SYSTEM_JOBID'],
planId: process.env['SYSTEM_PLANID'],
projectId: process.env['SYSTEM_TEAMPROJECTID'],
hub: process.env['SYSTEM_HOSTTYPE'],
uri: process.env['SYSTEM_COLLECTIONURI'],
managedIdentityId: process.env['VSCODE_ESRP_CLIENT_ID'],
managedIdentityTenantId: process.env['VSCODE_ESRP_TENANT_ID'],
serviceConnectionId: process.env['VSCODE_ESRP_SERVICE_CONNECTION_ID'],
tempDirectory: os.tmpdir(),
systemAccessToken: encryptedTokenPath,
encryptionKey: encryptionDetailsPath
};
const args = [
esrpCliPath,
'vsts.sign',
'-a', process.env['ESRP_CLIENT_ID']!,
'-d', process.env['ESRP_TENANT_ID']!,
'-k', JSON.stringify({ akv: 'vscode-esrp' }),
'-z', JSON.stringify({ akv: 'vscode-esrp', cert: 'esrp-sign' }),
'-f', folderPath,
'-p', patternPath,
'-u', 'false',
'-x', 'regularSigning',
'-b', 'input.json',
'-l', 'AzSecPack_PublisherPolicyProd.xml',
'-y', 'inlineSignParams',
'-j', paramsPath,
'-c', '9997',
'-t', '120',
'-g', '10',
'-v', 'Tls12',
'-s', 'https://api.esrp.microsoft.com/api/v1',
'-m', '0',
'-o', 'Microsoft',
'-i', 'https://www.microsoft.com',
'-n', '5',
'-r', 'true',
'-w', dotnetVersion,
'-skipAdoReportAttachment', 'false',
'-pendingAnalysisWaitTimeoutMinutes', '5',
'-adoTaskVersion', adoTaskVersion,
'-resourceUri', 'https://msazurecloud.onmicrosoft.com/api.esrp.microsoft.com',
'-esrpClientId', process.env['ESRP_CLIENT_ID']!,
'-useMSIAuthentication', 'true',
'-federatedTokenData', JSON.stringify(federatedTokenData)
];
try {
cp.execFileSync('dotnet', args, { stdio: 'inherit' });
} catch (err) {
console.error('ESRP failed');
console.error(err);
process.exit(1);
}
}
if (require.main === module) {
main(process.argv.slice(2));
process.exit(0);
}
================================================
FILE: build/azure-pipelines/common/telemetry-config.json
================================================
[
{
"eventPrefix": "typescript-language-features/",
"sourceDirs": [
"../../s/extensions/typescript-language-features"
],
"excludedDirs": [],
"applyEndpoints": true
},
{
"eventPrefix": "git/",
"sourceDirs": [
"../../s/extensions/git"
],
"excludedDirs": [],
"applyEndpoints": true
},
{
"eventPrefix": "extension-telemetry/",
"sourceDirs": [
"vscode-extension-telemetry"
],
"excludedDirs": [],
"applyEndpoints": true
},
{
"eventPrefix": "vscode-markdown/",
"sourceDirs": [
"../../s/extensions/markdown-language-features"
],
"excludedDirs": [],
"applyEndpoints": true
},
{
"eventPrefix": "html-language-features/",
"sourceDirs": [
"../../s/extensions/html-language-features",
"vscode-html-languageservice"
],
"excludedDirs": [],
"applyEndpoints": true
},
{
"eventPrefix": "json-language-features/",
"sourceDirs": [
"../../s/extensions/json-language-features",
"vscode-json-languageservice"
],
"excludedDirs": [],
"applyEndpoints": true
},
{
"eventPrefix": "ms-vscode.node/",
"sourceDirs": [
"vscode-chrome-debug-core",
"vscode-node-debug"
],
"excludedDirs": [],
"applyEndpoints": true,
"patchDebugEvents": true
}
]
================================================
FILE: build/azure-pipelines/config/CredScanSuppressions.json
================================================
{
"tool": "Credential Scanner",
"suppressions": [
{
"file": [
"src/vs/base/test/common/uri.test.ts",
"src/vs/workbench/api/test/browser/extHostTelemetry.test.ts"
],
"_justification": "These are dummy credentials in tests."
},
{
"file": [
".build/linux/rpm/x86_64/rpmbuild/BUILD/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/x86_64/rpmbuild/BUILD/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/rpm/armv7hl/rpmbuild/BUILD/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/armv7hl/rpmbuild/BUILD/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/rpm/aarch64/rpmbuild/BUILD/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/aarch64/rpmbuild/BUILD/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-x64/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-x64/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-x64/stage/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-x64/stage/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-x64/prime/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-x64/prime/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-x64/parts/code/build/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-x64/parts/code/install/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-x64/parts/code/src/usr/share/code/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-x64/parts/code/build/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-x64/parts/code/install/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-x64/parts/code/src/usr/share/code/resources/app/extensions/emmet/dist/node/emmetNodeMain.js"
],
"_justification": "These are safe to ignore, since they are built artifacts (stable)."
},
{
"file": [
".build/linux/rpm/x86_64/rpmbuild/BUILD/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/x86_64/rpmbuild/BUILD/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/rpm/armv7hl/rpmbuild/BUILD/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/armv7hl/rpmbuild/BUILD/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/rpm/aarch64/rpmbuild/BUILD/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/aarch64/rpmbuild/BUILD/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-insiders-x64/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-insiders-x64/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-insiders-x64/stage/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-insiders-x64/stage/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-insiders-x64/prime/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-insiders-x64/prime/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-insiders-x64/parts/code/build/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-insiders-x64/parts/code/install/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-insiders-x64/parts/code/src/usr/share/code-insiders/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-insiders-x64/parts/code/build/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-insiders-x64/parts/code/install/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-insiders-x64/parts/code/src/usr/share/code-insiders/resources/app/extensions/emmet/dist/node/emmetNodeMain.js"
],
"_justification": "These are safe to ignore, since they are built artifacts (insiders)."
},
{
"file": [
".build/linux/rpm/x86_64/rpmbuild/BUILD/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/x86_64/rpmbuild/BUILD/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/rpm/armv7hl/rpmbuild/BUILD/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/armv7hl/rpmbuild/BUILD/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/rpm/aarch64/rpmbuild/BUILD/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/rpm/aarch64/rpmbuild/BUILD/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-exploration-x64/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-exploration-x64/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-exploration-x64/stage/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-exploration-x64/stage/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-exploration-x64/prime/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-exploration-x64/prime/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-exploration-x64/parts/code/build/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-exploration-x64/parts/code/install/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-exploration-x64/parts/code/src/usr/share/code-exploration/resources/app/extensions/github-authentication/dist/extension.js",
".build/linux/snap/x64/code-exploration-x64/parts/code/build/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-exploration-x64/parts/code/install/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js",
".build/linux/snap/x64/code-exploration-x64/parts/code/src/usr/share/code-exploration/resources/app/extensions/emmet/dist/node/emmetNodeMain.js"
],
"_justification": "These are safe to ignore, since they are built artifacts (exploration)."
},
{
"file": [
".build/web/extensions/github-authentication/dist/browser/extension.js",
".build/web/extensions/emmet/dist/browser/emmetBrowserMain.js.map",
".build/web/extensions/emmet/dist/browser/emmetBrowserMain.js"
],
"_justification": "These are safe to ignore, since they are built artifacts (web)."
}
]
}
================================================
FILE: build/azure-pipelines/config/tsaoptions.json
================================================
{
"codebaseName": "devdiv_microsoft_vscode",
"serviceTreeID": "79c048b2-322f-4ed5-a1ea-252a1250e4b3",
"instanceUrl": "https://devdiv.visualstudio.com/defaultcollection",
"projectName": "DevDiv",
"areaPath": "DevDiv\\VS Code (compliance tracking only)\\Visual Studio Code Client",
"notificationAliases": [
"monacotools@microsoft.com"
],
"validateToolOutput": "None",
"allTools": true
}
================================================
FILE: build/azure-pipelines/darwin/app-entitlements.plist
================================================
com.apple.security.cs.allow-jit
com.apple.security.device.audio-input
com.apple.security.device.camera
com.apple.security.automation.apple-events
================================================
FILE: build/azure-pipelines/darwin/cli-build-darwin.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_BUILD_MACOS
type: boolean
default: false
- name: VSCODE_BUILD_MACOS_ARM64
type: boolean
default: false
- name: VSCODE_CHECK_ONLY
type: boolean
default: false
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../cli/cli-apply-patches.yml@self
- task: Npm@1
displayName: Download openssl prebuilt
inputs:
command: custom
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.11
customRegistry: useFeed
customFeed: "Monaco/openssl-prebuilt"
workingDir: $(Build.ArtifactStagingDirectory)
- script: |
set -e
mkdir $(Build.ArtifactStagingDirectory)/openssl
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.11.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
displayName: Extract openssl prebuilt
- template: ../cli/install-rust-posix.yml@self
parameters:
targets:
- ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
- x86_64-apple-darwin
- ${{ if eq(parameters.VSCODE_BUILD_MACOS_ARM64, true) }}:
- aarch64-apple-darwin
- ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: x86_64-apple-darwin
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_darwin_x64_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-osx/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-osx/include
- ${{ if eq(parameters.VSCODE_BUILD_MACOS_ARM64, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: aarch64-apple-darwin
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_darwin_arm64_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-osx/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-osx/include
- ${{ if not(parameters.VSCODE_CHECK_ONLY) }}:
- ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/unsigned_vscode_cli_darwin_x64_cli.zip
artifactName: unsigned_vscode_cli_darwin_x64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code macOS x64 CLI (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish unsigned_vscode_cli_darwin_x64_cli artifact
- ${{ if eq(parameters.VSCODE_BUILD_MACOS_ARM64, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/unsigned_vscode_cli_darwin_arm64_cli.zip
artifactName: unsigned_vscode_cli_darwin_arm64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code macOS arm64 CLI (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish unsigned_vscode_cli_darwin_arm64_cli artifact
================================================
FILE: build/azure-pipelines/darwin/helper-gpu-entitlements.plist
================================================
com.apple.security.cs.allow-jit
================================================
FILE: build/azure-pipelines/darwin/helper-plugin-entitlements.plist
================================================
com.apple.security.cs.allow-jit
com.apple.security.cs.allow-unsigned-executable-memory
com.apple.security.cs.disable-library-validation
================================================
FILE: build/azure-pipelines/darwin/helper-renderer-entitlements.plist
================================================
com.apple.security.cs.allow-jit
================================================
FILE: build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml
================================================
parameters:
- name: VSCODE_BUILD_MACOS
type: boolean
- name: VSCODE_BUILD_MACOS_ARM64
type: boolean
- name: VSCODE_QUALITY
type: string
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- script: node build/setup-npm-registry.js $NPM_REGISTRY build
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install build dependencies
- template: ../cli/cli-darwin-sign.yml@self
parameters:
VSCODE_CLI_ARTIFACTS:
- ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
- unsigned_vscode_cli_darwin_x64_cli
- ${{ if eq(parameters.VSCODE_BUILD_MACOS_ARM64, true) }}:
- unsigned_vscode_cli_darwin_arm64_cli
================================================
FILE: build/azure-pipelines/darwin/product-build-darwin-sign.yml
================================================
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- task: UseDotNet@2
inputs:
version: 6.x
- task: EsrpCodeSigning@5
inputs:
UseMSIAuthentication: true
ConnectedServiceName: vscode-esrp
AppRegistrationClientId: $(ESRP_CLIENT_ID)
AppRegistrationTenantId: $(ESRP_TENANT_ID)
AuthAKVName: vscode-esrp
AuthSignCertName: esrp-sign
FolderPath: .
Pattern: noop
displayName: 'Install ESRP Tooling'
- script: |
# For legacy purposes, arch for x64 is just 'darwin'
case $VSCODE_ARCH in
x64) ASSET_ID="darwin" ;;
arm64) ASSET_ID="darwin-arm64" ;;
universal) ASSET_ID="darwin-universal" ;;
esac
echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID"
displayName: Set asset id variable
- script: |
if [ -z "$(ASSET_ID)" ]; then
echo "ASSET_ID is empty"
exit 1
else
echo "ASSET_ID is set to $(ASSET_ID)"
fi
displayName: Check ASSET_ID variable
- download: current
artifact: unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive
displayName: Download $(VSCODE_ARCH) artifact
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll sign-darwin $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive VSCode-darwin-$(VSCODE_ARCH).zip
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll notarize-darwin $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive VSCode-darwin-$(VSCODE_ARCH).zip
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Notarize
- script: unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-$(VSCODE_ARCH).zip -d $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)
displayName: Extract signed app
- script: |
set -e
APP_ROOT="$(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)"
APP_NAME="`ls $APP_ROOT | head -n 1`"
APP_PATH="$APP_ROOT/$APP_NAME"
codesign -dv --deep --verbose=4 "$APP_PATH"
"$APP_PATH/Contents/Resources/app/bin/code" --export-default-configuration=.build
displayName: Verify signature
condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64'))
- script: mv $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-x64.zip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin.zip
displayName: Rename x64 build to its legacy name
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'))
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-$(ASSET_ID).zip
artifactName: vscode_client_darwin_$(VSCODE_ARCH)_archive
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)
sbomPackageName: "VS Code macOS $(VSCODE_ARCH)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish client archive
================================================
FILE: build/azure-pipelines/darwin/product-build-darwin-test.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_RUN_UNIT_TESTS
type: boolean
- name: VSCODE_RUN_INTEGRATION_TESTS
type: boolean
- name: VSCODE_RUN_SMOKE_TESTS
type: boolean
steps:
- script: npm exec -- npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Download Electron and Playwright
retryCountOnTaskFailure: 3
- ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: ./scripts/test.sh --tfs "Unit Tests"
displayName: Run unit tests (Electron)
timeoutInMinutes: 15
- script: npm run test-node
displayName: Run unit tests (node.js)
timeoutInMinutes: 15
- script: npm run test-browser-no-install -- --browser webkit --tfs "Browser Unit Tests"
env:
DEBUG: "*browser*"
displayName: Run unit tests (Browser, Webkit)
timeoutInMinutes: 30
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: ./scripts/test.sh --build --tfs "Unit Tests"
displayName: Run unit tests (Electron)
timeoutInMinutes: 15
- script: npm run test-node -- --build
displayName: Run unit tests (node.js)
timeoutInMinutes: 15
- script: npm run test-browser-no-install -- --build --browser webkit --tfs "Browser Unit Tests"
env:
DEBUG: "*browser*"
displayName: Run unit tests (Browser, Webkit)
timeoutInMinutes: 30
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
- script: |
set -e
npm run gulp \
compile-extension:configuration-editing \
compile-extension:css-language-features-server \
compile-extension:emmet \
compile-extension:git \
compile-extension:github-authentication \
compile-extension:html-language-features-server \
compile-extension:ipynb \
compile-extension:notebook-renderers \
compile-extension:json-language-features-server \
compile-extension:markdown-language-features \
compile-extension-media \
compile-extension:microsoft-authentication \
compile-extension:typescript-language-features \
compile-extension:vscode-api-tests \
compile-extension:vscode-colorize-tests \
compile-extension:vscode-colorize-perf-tests \
compile-extension:vscode-test-resolver
displayName: Build integration tests
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: ./scripts/test-integration --tfs "Integration Tests"
displayName: Run integration tests (Electron)
timeoutInMinutes: 20
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
# Figure out the full absolute path of the product we just built
# including the remote server and configure the integration tests
# to run with these builds instead of running out of sources.
set -e
APP_ROOT="$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)"
APP_NAME="`ls $APP_ROOT | head -n 1`"
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \
./scripts/test-integration.sh --build --tfs "Integration Tests"
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)
displayName: Run integration tests (Electron)
timeoutInMinutes: 20
- script: ./scripts/test-web-integration.sh --browser webkit
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)-web
displayName: Run integration tests (Browser, Webkit)
timeoutInMinutes: 20
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \
./scripts/test-remote-integration.sh
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)
displayName: Run integration tests (Remote)
timeoutInMinutes: 20
- ${{ if eq(parameters.VSCODE_RUN_SMOKE_TESTS, true) }}:
- script: ps -ef
displayName: Diagnostics before smoke test run
continueOnError: true
condition: succeededOrFailed()
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: npm run compile
workingDirectory: test/smoke
displayName: Compile smoke tests
- script: npm run gulp compile-extension-media
displayName: Compile extensions for smoke tests
- script: npm run smoketest-no-compile -- --tracing
timeoutInMinutes: 20
displayName: Run smoke tests (Electron)
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
npm run smoketest-no-compile -- --tracing --build "$APP_ROOT/$APP_NAME"
timeoutInMinutes: 20
displayName: Run smoke tests (Electron)
- script: npm run smoketest-no-compile -- --web --tracing --headless
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)-web
timeoutInMinutes: 20
displayName: Run smoke tests (Browser, Chromium)
- script: |
set -e
npm run gulp compile-extension:vscode-test-resolver
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
npm run smoketest-no-compile -- --tracing --remote --build "$APP_ROOT/$APP_NAME"
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)
timeoutInMinutes: 20
displayName: Run smoke tests (Remote)
- script: ps -ef
displayName: Diagnostics after smoke test run
continueOnError: true
condition: succeededOrFailed()
- ${{ if or(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: .build/crashes
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: crash-dump-macos-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: crash-dump-macos-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: crash-dump-macos-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Crash Reports"
continueOnError: true
condition: failed()
# In order to properly symbolify above crash reports
# (if any), we need the compiled native modules too
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: node_modules
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: node-modules-macos-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: node-modules-macos-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: node-modules-macos-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Node Modules"
continueOnError: true
condition: failed()
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: .build/logs
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: logs-macos-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: logs-macos-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: logs-macos-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Log Files"
continueOnError: true
condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
testResultsFiles: "*-results.xml"
searchFolder: "$(Build.ArtifactStagingDirectory)/test-results"
condition: succeededOrFailed()
================================================
FILE: build/azure-pipelines/darwin/product-build-darwin-universal.yml
================================================
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
- script: node build/setup-npm-registry.js $NPM_REGISTRY build
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install build dependencies
- download: current
artifact: unsigned_vscode_client_darwin_x64_archive
displayName: Download x64 artifact
- download: current
artifact: unsigned_vscode_client_darwin_arm64_archive
displayName: Download arm64 artifact
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- script: |
set -e
unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_x64_archive/VSCode-darwin-x64.zip -d $(agent.builddirectory)/VSCode-darwin-x64
unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_arm64_archive/VSCode-darwin-arm64.zip -d $(agent.builddirectory)/VSCode-darwin-arm64
DEBUG=* node build/darwin/create-universal-app.js $(agent.builddirectory)
displayName: Create Universal App
- script: |
set -e
APP_ROOT="$(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)"
APP_NAME="`ls $APP_ROOT | head -n 1`"
APP_PATH="$APP_ROOT/$APP_NAME" node build/darwin/verify-macho.js universal
displayName: Verify arch of Mach-O objects
- script: |
set -e
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
security default-keychain -s $(agent.tempdirectory)/buildagent.keychain
security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12
security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign
export CODESIGN_IDENTITY=$(security find-identity -v -p codesigning $(agent.tempdirectory)/buildagent.keychain | grep -oEi "([0-9A-F]{40})" | head -n 1)
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain
DEBUG=electron-osx-sign* node build/darwin/sign.js $(agent.builddirectory)
displayName: Set Hardened Entitlements
- script: pushd $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH) && zip -r -X -y $(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH).zip * && popd
displayName: Archive build
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH).zip
artifactName: unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)
sbomPackageName: "VS Code macOS $(VSCODE_ARCH) (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish client archive
================================================
FILE: build/azure-pipelines/darwin/product-build-darwin.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_CIBUILD
type: boolean
- name: VSCODE_RUN_UNIT_TESTS
type: boolean
- name: VSCODE_RUN_INTEGRATION_TESTS
type: boolean
- name: VSCODE_RUN_SMOKE_TESTS
type: boolean
steps:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- checkout: self
fetchDepth: 1
retryCountOnTaskFailure: 3
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
- task: DownloadPipelineArtifact@2
inputs:
artifact: Compilation
path: $(Build.ArtifactStagingDirectory)
displayName: Download compilation output
- script: tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
displayName: Extract compilation output
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js darwin $VSCODE_ARCH > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- script: tar -xzf .build/node_modules_cache/cache.tgz
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
c++ --version
xcode-select -print-path
python3 -m pip install setuptools
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
env:
npm_config_arch: $(VSCODE_ARCH)
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
# Avoid using dlopen to load Kerberos on macOS which can cause missing libraries
# https://github.com/mongodb-js/kerberos/commit/04044d2814ad1d01e77f1ce87f26b03d86692cf2
# flipped the default to support legacy linux distros which shouldn't happen
# on macOS.
GYP_DEFINES: "kerberos_use_rtld=false"
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/azure-pipelines/distro/mixin-npm
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Mixin distro node modules
- script: |
set -e
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
mkdir -p .build/node_modules_cache
tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- template: ../common/install-builtin-extensions.yml@self
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'oss')) }}:
- script: node build/lib/policies darwin
displayName: Generate policy definitions
retryCountOnTaskFailure: 3
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
set -e
npm run gulp vscode-darwin-$(VSCODE_ARCH)-min-ci
echo "##vso[task.setvariable variable=BUILT_CLIENT]true"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build client
- script: |
set -e
npm run gulp vscode-reh-darwin-$(VSCODE_ARCH)-min-ci
mv ../vscode-reh-darwin-$(VSCODE_ARCH) ../vscode-server-darwin-$(VSCODE_ARCH) # TODO@joaomoreno
ARCHIVE_PATH=".build/darwin/server/vscode-server-darwin-$(VSCODE_ARCH).zip"
mkdir -p $(dirname $ARCHIVE_PATH)
(cd .. && zip -Xry $(Build.SourcesDirectory)/$ARCHIVE_PATH vscode-server-darwin-$(VSCODE_ARCH))
echo "##vso[task.setvariable variable=SERVER_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server
- script: |
set -e
npm run gulp vscode-reh-web-darwin-$(VSCODE_ARCH)-min-ci
mv ../vscode-reh-web-darwin-$(VSCODE_ARCH) ../vscode-server-darwin-$(VSCODE_ARCH)-web # TODO@joaomoreno
ARCHIVE_PATH=".build/darwin/server/vscode-server-darwin-$(VSCODE_ARCH)-web.zip"
mkdir -p $(dirname $ARCHIVE_PATH)
(cd .. && zip -Xry $(Build.SourcesDirectory)/$ARCHIVE_PATH vscode-server-darwin-$(VSCODE_ARCH)-web)
echo "##vso[task.setvariable variable=WEB_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server (web)
- ${{ else }}:
- script: npm run gulp transpile-client-esbuild transpile-extensions
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Transpile
- ${{ if or(eq(parameters.VSCODE_RUN_UNIT_TESTS, true), eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
- template: product-build-darwin-test.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_RUN_UNIT_TESTS: ${{ parameters.VSCODE_RUN_UNIT_TESTS }}
VSCODE_RUN_INTEGRATION_TESTS: ${{ parameters.VSCODE_RUN_INTEGRATION_TESTS }}
VSCODE_RUN_SMOKE_TESTS: ${{ parameters.VSCODE_RUN_SMOKE_TESTS }}
- ${{ elseif and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'oss')) }}:
- task: DownloadPipelineArtifact@2
inputs:
artifact: unsigned_vscode_cli_darwin_$(VSCODE_ARCH)_cli
patterns: "**"
path: $(Build.ArtifactStagingDirectory)/cli
displayName: Download VS Code CLI
- script: |
set -e
APP_ROOT="$(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)"
APP_NAME="`ls $APP_ROOT | head -n 1`"
APP_PATH="$APP_ROOT/$APP_NAME"
unzip $(Build.ArtifactStagingDirectory)/cli/*.zip -d $(Build.ArtifactStagingDirectory)/cli
CLI_APP_NAME=$(node -p "require(\"$APP_PATH/Contents/Resources/app/product.json\").tunnelApplicationName")
APP_NAME=$(node -p "require(\"$APP_PATH/Contents/Resources/app/product.json\").applicationName")
mv "$(Build.ArtifactStagingDirectory)/cli/$APP_NAME" "$APP_PATH/Contents/Resources/app/bin/$CLI_APP_NAME"
chmod +x "$APP_PATH/Contents/Resources/app/bin/$CLI_APP_NAME"
displayName: Make CLI executable
- script: |
set -e
APP_ROOT="$(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)"
APP_NAME="`ls $APP_ROOT | head -n 1`"
APP_PATH="$APP_ROOT/$APP_NAME" node build/darwin/verify-macho.js $(VSCODE_ARCH)
APP_PATH="$(Agent.BuildDirectory)/vscode-server-darwin-$(VSCODE_ARCH)" node build/darwin/verify-macho.js $(VSCODE_ARCH)
displayName: Verify arch of Mach-O objects
# Setting hardened entitlements is a requirement for:
# * Apple notarization
# * Running tests on Big Sur (because Big Sur has additional security precautions)
- script: |
set -e
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
security default-keychain -s $(agent.tempdirectory)/buildagent.keychain
security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12
security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign
export CODESIGN_IDENTITY=$(security find-identity -v -p codesigning $(agent.tempdirectory)/buildagent.keychain | grep -oEi "([0-9A-F]{40})" | head -n 1)
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain
DEBUG=electron-osx-sign* node build/darwin/sign.js $(agent.builddirectory)
displayName: Set Hardened Entitlements
- script: |
set -e
ARCHIVE_PATH=".build/darwin/client/VSCode-darwin-$(VSCODE_ARCH).zip"
mkdir -p $(dirname $ARCHIVE_PATH)
(cd ../VSCode-darwin-$(VSCODE_ARCH) && zip -Xry $(Build.SourcesDirectory)/$ARCHIVE_PATH *)
echo "##vso[task.setvariable variable=CLIENT_PATH]$ARCHIVE_PATH"
condition: and(succeededOrFailed(), eq(variables['BUILT_CLIENT'], 'true'))
displayName: Package client
- script: echo "##vso[task.setvariable variable=ARTIFACT_PREFIX]attempt$(System.JobAttempt)_"
condition: and(succeededOrFailed(), notIn(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues'))
displayName: Generate artifact prefix
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(CLIENT_PATH)
artifactName: $(ARTIFACT_PREFIX)unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)
sbomPackageName: "VS Code macOS $(VSCODE_ARCH) (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish client archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SERVER_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_server_darwin_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-darwin-$(VSCODE_ARCH)
sbomPackageName: "VS Code macOS $(VSCODE_ARCH) Server"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['SERVER_PATH'], ''))
displayName: Publish server archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(WEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_web_darwin_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-darwin-$(VSCODE_ARCH)-web
sbomPackageName: "VS Code macOS $(VSCODE_ARCH) Web"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], ''))
displayName: Publish web server archive
================================================
FILE: build/azure-pipelines/distro/download-distro.yml
================================================
steps:
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
# TODO@joaomoreno: Keep pwsh once we move out of running entire jobs in containers
- pwsh: |
"machine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$Home/_netrc" -Encoding ASCII
condition: and(succeeded(), contains(variables['Agent.OS'], 'windows'))
displayName: Setup distro auth (Windows)
- pwsh: |
$ErrorActionPreference = "Stop"
$ArchivePath = "$(Agent.TempDirectory)/distro.zip"
$PackageJson = Get-Content -Path package.json -Raw | ConvertFrom-Json
$DistroVersion = $PackageJson.distro
Invoke-WebRequest -Uri "https://api.github.com/repos/microsoft/vscode-distro/zipball/$DistroVersion" `
-OutFile $ArchivePath `
-Headers @{ "Accept" = "application/vnd.github+json"; "Authorization" = "Bearer $(github-distro-mixin-password)"; "X-GitHub-Api-Version" = "2022-11-28" }
New-Item -ItemType Directory -Path .build -Force
Expand-Archive -Path $ArchivePath -DestinationPath .build
Rename-Item -Path ".build/microsoft-vscode-distro-$DistroVersion" -NewName distro
condition: and(succeeded(), contains(variables['Agent.OS'], 'windows'))
displayName: Download distro (Windows)
- script: |
mkdir -p .build
cat << EOF | tee ~/.netrc .build/.netrc > /dev/null
machine github.com
login vscode
password $(github-distro-mixin-password)
EOF
condition: and(succeeded(), not(contains(variables['Agent.OS'], 'windows')))
displayName: Setup distro auth (non-Windows)
- script: |
set -e
ArchivePath="$(Agent.TempDirectory)/distro.zip"
DistroVersion=$(node -p "require('./package.json').distro")
curl -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $(github-distro-mixin-password)" \
-H "X-GitHub-Api-Version: 2022-11-28" \
-o $ArchivePath \
-L "https://api.github.com/repos/microsoft/vscode-distro/zipball/$DistroVersion"
unzip $ArchivePath -d .build
mv .build/microsoft-vscode-distro-$DistroVersion .build/distro
condition: and(succeeded(), not(contains(variables['Agent.OS'], 'windows')))
displayName: Download distro (non-Windows)
================================================
FILE: build/azure-pipelines/distro/mixin-npm.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const { dirs } = require('../../npm/dirs');
function log(...args) {
console.log(`[${new Date().toLocaleTimeString('en', { hour12: false })}]`, '[distro]', ...args);
}
function mixin(mixinPath) {
if (!fs_1.default.existsSync(`${mixinPath}/node_modules`)) {
log(`Skipping distro npm dependencies: ${mixinPath} (no node_modules)`);
return;
}
log(`Mixing in distro npm dependencies: ${mixinPath}`);
const distroPackageJson = JSON.parse(fs_1.default.readFileSync(`${mixinPath}/package.json`, 'utf8'));
const targetPath = path_1.default.relative('.build/distro/npm', mixinPath);
for (const dependency of Object.keys(distroPackageJson.dependencies)) {
fs_1.default.rmSync(`./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true });
fs_1.default.cpSync(`${mixinPath}/node_modules/${dependency}`, `./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true, dereference: true });
}
log(`Mixed in distro npm dependencies: ${mixinPath} ✔︎`);
}
function main() {
log(`Mixing in distro npm dependencies...`);
const mixinPaths = dirs.filter(d => /^.build\/distro\/npm/.test(d));
for (const mixinPath of mixinPaths) {
mixin(mixinPath);
}
}
main();
//# sourceMappingURL=mixin-npm.js.map
================================================
FILE: build/azure-pipelines/distro/mixin-npm.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
const { dirs } = require('../../npm/dirs') as { dirs: string[] };
function log(...args: any[]): void {
console.log(`[${new Date().toLocaleTimeString('en', { hour12: false })}]`, '[distro]', ...args);
}
function mixin(mixinPath: string) {
if (!fs.existsSync(`${mixinPath}/node_modules`)) {
log(`Skipping distro npm dependencies: ${mixinPath} (no node_modules)`);
return;
}
log(`Mixing in distro npm dependencies: ${mixinPath}`);
const distroPackageJson = JSON.parse(fs.readFileSync(`${mixinPath}/package.json`, 'utf8'));
const targetPath = path.relative('.build/distro/npm', mixinPath);
for (const dependency of Object.keys(distroPackageJson.dependencies)) {
fs.rmSync(`./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true });
fs.cpSync(`${mixinPath}/node_modules/${dependency}`, `./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true, dereference: true });
}
log(`Mixed in distro npm dependencies: ${mixinPath} ✔︎`);
}
function main() {
log(`Mixing in distro npm dependencies...`);
const mixinPaths = dirs.filter(d => /^.build\/distro\/npm/.test(d));
for (const mixinPath of mixinPaths) {
mixin(mixinPath);
}
}
main();
================================================
FILE: build/azure-pipelines/distro/mixin-quality.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
function log(...args) {
console.log(`[${new Date().toLocaleTimeString('en', { hour12: false })}]`, '[distro]', ...args);
}
function main() {
const quality = process.env['VSCODE_QUALITY'];
if (!quality) {
throw new Error('Missing VSCODE_QUALITY, skipping mixin');
}
log(`Mixing in distro quality...`);
const basePath = `.build/distro/mixin/${quality}`;
for (const name of fs_1.default.readdirSync(basePath)) {
const distroPath = path_1.default.join(basePath, name);
const ossPath = path_1.default.relative(basePath, distroPath);
if (ossPath === 'product.json') {
const distro = JSON.parse(fs_1.default.readFileSync(distroPath, 'utf8'));
const oss = JSON.parse(fs_1.default.readFileSync(ossPath, 'utf8'));
let builtInExtensions = oss.builtInExtensions;
if (Array.isArray(distro.builtInExtensions)) {
log('Overwriting built-in extensions:', distro.builtInExtensions.map(e => e.name));
builtInExtensions = distro.builtInExtensions;
}
else if (distro.builtInExtensions) {
const include = distro.builtInExtensions['include'] ?? [];
const exclude = distro.builtInExtensions['exclude'] ?? [];
log('OSS built-in extensions:', builtInExtensions.map(e => e.name));
log('Including built-in extensions:', include.map(e => e.name));
log('Excluding built-in extensions:', exclude);
builtInExtensions = builtInExtensions.filter(ext => !include.find(e => e.name === ext.name) && !exclude.find(name => name === ext.name));
builtInExtensions = [...builtInExtensions, ...include];
log('Final built-in extensions:', builtInExtensions.map(e => e.name));
}
else {
log('Inheriting OSS built-in extensions', builtInExtensions.map(e => e.name));
}
const result = { webBuiltInExtensions: oss.webBuiltInExtensions, ...distro, builtInExtensions };
fs_1.default.writeFileSync(ossPath, JSON.stringify(result, null, '\t'), 'utf8');
}
else {
fs_1.default.cpSync(distroPath, ossPath, { force: true, recursive: true });
}
log(distroPath, '✔︎');
}
}
main();
//# sourceMappingURL=mixin-quality.js.map
================================================
FILE: build/azure-pipelines/distro/mixin-quality.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
interface IBuiltInExtension {
readonly name: string;
readonly version: string;
readonly repo: string;
readonly metadata: any;
}
interface OSSProduct {
readonly builtInExtensions: IBuiltInExtension[];
readonly webBuiltInExtensions?: IBuiltInExtension[];
}
interface Product {
readonly builtInExtensions?: IBuiltInExtension[] | { 'include'?: IBuiltInExtension[]; 'exclude'?: string[] };
readonly webBuiltInExtensions?: IBuiltInExtension[];
}
function log(...args: any[]): void {
console.log(`[${new Date().toLocaleTimeString('en', { hour12: false })}]`, '[distro]', ...args);
}
function main() {
const quality = process.env['VSCODE_QUALITY'];
if (!quality) {
throw new Error('Missing VSCODE_QUALITY, skipping mixin');
}
log(`Mixing in distro quality...`);
const basePath = `.build/distro/mixin/${quality}`;
for (const name of fs.readdirSync(basePath)) {
const distroPath = path.join(basePath, name);
const ossPath = path.relative(basePath, distroPath);
if (ossPath === 'product.json') {
const distro = JSON.parse(fs.readFileSync(distroPath, 'utf8')) as Product;
const oss = JSON.parse(fs.readFileSync(ossPath, 'utf8')) as OSSProduct;
let builtInExtensions = oss.builtInExtensions;
if (Array.isArray(distro.builtInExtensions)) {
log('Overwriting built-in extensions:', distro.builtInExtensions.map(e => e.name));
builtInExtensions = distro.builtInExtensions;
} else if (distro.builtInExtensions) {
const include = distro.builtInExtensions['include'] ?? [];
const exclude = distro.builtInExtensions['exclude'] ?? [];
log('OSS built-in extensions:', builtInExtensions.map(e => e.name));
log('Including built-in extensions:', include.map(e => e.name));
log('Excluding built-in extensions:', exclude);
builtInExtensions = builtInExtensions.filter(ext => !include.find(e => e.name === ext.name) && !exclude.find(name => name === ext.name));
builtInExtensions = [...builtInExtensions, ...include];
log('Final built-in extensions:', builtInExtensions.map(e => e.name));
} else {
log('Inheriting OSS built-in extensions', builtInExtensions.map(e => e.name));
}
const result = { webBuiltInExtensions: oss.webBuiltInExtensions, ...distro, builtInExtensions };
fs.writeFileSync(ossPath, JSON.stringify(result, null, '\t'), 'utf8');
} else {
fs.cpSync(distroPath, ossPath, { force: true, recursive: true });
}
log(distroPath, '✔︎');
}
}
main();
================================================
FILE: build/azure-pipelines/distro-build.yml
================================================
pool:
name: 1es-ubuntu-22.04-x64
os: linux
trigger:
branches:
include: ["main", "release/*"]
pr: none
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- template: ./distro/download-distro.yml@self
================================================
FILE: build/azure-pipelines/linux/.gitignore
================================================
pat
================================================
FILE: build/azure-pipelines/linux/apt-retry.sh
================================================
#!/bin/sh
################################################################################
## Copied from https://github.com/actions/runner-images/blob/ubuntu22/20240825.1/images/ubuntu/scripts/build/configure-apt-mock.sh
################################################################################
i=1
while [ $i -le 30 ];do
err=$(mktemp)
"$@" 2>$err
# no errors, break the loop and continue normal flow
test -f $err || break
cat $err >&2
retry=false
if grep -q 'Could not get lock' $err;then
# apt db locked needs retry
retry=true
elif grep -q 'Could not open file /var/lib/apt/lists' $err;then
# apt update is not completed, needs retry
retry=true
elif grep -q 'IPC connect call failed' $err;then
# the delay should help with gpg-agent not ready
retry=true
elif grep -q 'Temporary failure in name resolution' $err;then
# It looks like DNS is not updated with random generated hostname yet
retry=true
elif grep -q 'dpkg frontend is locked by another process' $err;then
# dpkg process is busy by another process
retry=true
fi
rm $err
if [ $retry = false ]; then
break
fi
sleep 5
echo "...retry $i"
i=$((i + 1))
done
================================================
FILE: build/azure-pipelines/linux/cli-build-linux.yml
================================================
parameters:
- name: VSCODE_BUILD_LINUX
type: boolean
default: false
- name: VSCODE_BUILD_LINUX_ARM64
type: boolean
default: false
- name: VSCODE_BUILD_LINUX_ARMHF
type: boolean
default: false
- name: VSCODE_CHECK_ONLY
type: boolean
default: false
- name: VSCODE_QUALITY
type: string
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../cli/cli-apply-patches.yml@self
- task: Npm@1
displayName: Download openssl prebuilt
inputs:
command: custom
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.11
customRegistry: useFeed
customFeed: "Monaco/openssl-prebuilt"
workingDir: $(Build.ArtifactStagingDirectory)
- script: |
set -e
mkdir $(Build.ArtifactStagingDirectory)/openssl
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.11.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
displayName: Extract openssl prebuilt
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/setup-npm-registry.js $NPM_REGISTRY build
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install build dependencies
- script: |
set -e
mkdir -p $(Build.SourcesDirectory)/.build
displayName: Create .build folder for misc dependencies
- template: ../cli/install-rust-posix.yml@self
parameters:
targets:
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARM64, true) }}:
- aarch64-unknown-linux-gnu
- ${{ if eq(parameters.VSCODE_BUILD_LINUX, true) }}:
- x86_64-unknown-linux-gnu
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true) }}:
- armv7-unknown-linux-gnueabihf
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARM64, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: aarch64-unknown-linux-gnu
VSCODE_CLI_ARTIFACT: vscode_cli_linux_arm64_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-linux/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-linux/include
SYSROOT_ARCH: arm64
- ${{ if eq(parameters.VSCODE_BUILD_LINUX, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: x86_64-unknown-linux-gnu
VSCODE_CLI_ARTIFACT: vscode_cli_linux_x64_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-linux/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-linux/include
SYSROOT_ARCH: amd64
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: armv7-unknown-linux-gnueabihf
VSCODE_CLI_ARTIFACT: vscode_cli_linux_armhf_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm-linux/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm-linux/include
SYSROOT_ARCH: armhf
- ${{ if not(parameters.VSCODE_CHECK_ONLY) }}:
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/vscode_cli_linux_armhf_cli.tar.gz
artifactName: vscode_cli_linux_armhf_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Linux armhf CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish vscode_cli_linux_armhf_cli artifact
- ${{ if eq(parameters.VSCODE_BUILD_LINUX, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/vscode_cli_linux_x64_cli.tar.gz
artifactName: vscode_cli_linux_x64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Linux x64 CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish vscode_cli_linux_x64_cli artifact
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARM64, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/vscode_cli_linux_arm64_cli.tar.gz
artifactName: vscode_cli_linux_arm64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Linux arm64 CLI"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish vscode_cli_linux_arm64_cli artifact
================================================
FILE: build/azure-pipelines/linux/product-build-linux-test.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_RUN_UNIT_TESTS
type: boolean
- name: VSCODE_RUN_INTEGRATION_TESTS
type: boolean
- name: VSCODE_RUN_SMOKE_TESTS
type: boolean
- name: PUBLISH_TASK_NAME
type: string
default: PublishPipelineArtifact@0
steps:
- script: npm exec -- npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Download Electron and Playwright
retryCountOnTaskFailure: 3
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
ELECTRON_ROOT=.build/electron
sudo chown root $APP_ROOT/chrome-sandbox
sudo chown root $ELECTRON_ROOT/chrome-sandbox
sudo chmod 4755 $APP_ROOT/chrome-sandbox
sudo chmod 4755 $ELECTRON_ROOT/chrome-sandbox
stat $APP_ROOT/chrome-sandbox
stat $ELECTRON_ROOT/chrome-sandbox
displayName: Change setuid helper binary permission
- ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: ./scripts/test.sh --tfs "Unit Tests"
env:
DISPLAY: ":10"
displayName: Run unit tests (Electron)
timeoutInMinutes: 15
- script: npm run test-node
displayName: Run unit tests (node.js)
timeoutInMinutes: 15
- script: npm run test-browser-no-install -- --browser chromium --tfs "Browser Unit Tests"
env:
DEBUG: "*browser*"
displayName: Run unit tests (Browser, Chromium)
timeoutInMinutes: 15
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: ./scripts/test.sh --build --tfs "Unit Tests"
displayName: Run unit tests (Electron)
timeoutInMinutes: 15
- script: npm run test-node -- --build
displayName: Run unit tests (node.js)
timeoutInMinutes: 15
- script: npm run test-browser-no-install -- --build --browser chromium --tfs "Browser Unit Tests"
env:
DEBUG: "*browser*"
displayName: Run unit tests (Browser, Chromium)
timeoutInMinutes: 15
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
- script: |
set -e
npm run gulp \
compile-extension:configuration-editing \
compile-extension:css-language-features-server \
compile-extension:emmet \
compile-extension:git \
compile-extension:github-authentication \
compile-extension:html-language-features-server \
compile-extension:ipynb \
compile-extension:notebook-renderers \
compile-extension:json-language-features-server \
compile-extension:markdown-language-features \
compile-extension-media \
compile-extension:microsoft-authentication \
compile-extension:typescript-language-features \
compile-extension:vscode-api-tests \
compile-extension:vscode-colorize-tests \
compile-extension:vscode-colorize-perf-tests \
compile-extension:vscode-test-resolver
displayName: Build integration tests
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: ./scripts/test-integration.sh --tfs "Integration Tests"
env:
DISPLAY: ":10"
displayName: Run integration tests (Electron)
timeoutInMinutes: 20
- script: ./scripts/test-web-integration.sh --browser chromium
displayName: Run integration tests (Browser, Chromium)
timeoutInMinutes: 20
- script: ./scripts/test-remote-integration.sh
displayName: Run integration tests (Remote)
timeoutInMinutes: 20
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
# Figure out the full absolute path of the product we just built
# including the remote server and configure the integration tests
# to run with these builds instead of running out of sources.
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName")
INTEGRATION_TEST_APP_NAME="$APP_NAME" \
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \
./scripts/test-integration.sh --build --tfs "Integration Tests"
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-linux-$(VSCODE_ARCH)
displayName: Run integration tests (Electron)
timeoutInMinutes: 20
- script: ./scripts/test-web-integration.sh --browser chromium
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-linux-$(VSCODE_ARCH)-web
displayName: Run integration tests (Browser, Chromium)
timeoutInMinutes: 20
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName")
INTEGRATION_TEST_APP_NAME="$APP_NAME" \
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \
./scripts/test-remote-integration.sh
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-linux-$(VSCODE_ARCH)
displayName: Run integration tests (Remote)
timeoutInMinutes: 20
- ${{ if eq(parameters.VSCODE_RUN_SMOKE_TESTS, true) }}:
- script: |
set -e
ps -ef
cat /proc/sys/fs/inotify/max_user_watches
lsof | wc -l
displayName: Diagnostics before smoke test run (processes, max_user_watches, number of opened file handles)
continueOnError: true
condition: succeededOrFailed()
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: npm run compile
workingDirectory: test/smoke
displayName: Compile smoke tests
- script: npm run gulp compile-extension:markdown-language-features compile-extension:ipynb compile-extension-media compile-extension:vscode-test-resolver
displayName: Build extensions for smoke tests
- script: npm run gulp node
displayName: Download node.js for remote smoke tests
retryCountOnTaskFailure: 3
- script: npm run smoketest-no-compile -- --tracing
timeoutInMinutes: 20
displayName: Run smoke tests (Electron)
- script: npm run smoketest-no-compile -- --web --tracing --headless --electronArgs="--disable-dev-shm-usage"
timeoutInMinutes: 20
displayName: Run smoke tests (Browser, Chromium)
- script: npm run smoketest-no-compile -- --remote --tracing
timeoutInMinutes: 20
displayName: Run smoke tests (Remote)
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: npm run smoketest-no-compile -- --tracing --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
timeoutInMinutes: 20
displayName: Run smoke tests (Electron)
- script: npm run smoketest-no-compile -- --web --tracing --headless --electronArgs="--disable-dev-shm-usage"
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-linux-$(VSCODE_ARCH)-web
timeoutInMinutes: 20
displayName: Run smoke tests (Browser, Chromium)
- script: |
set -e
npm run gulp compile-extension:vscode-test-resolver
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-server-linux-$(VSCODE_ARCH)" \
npm run smoketest-no-compile -- --tracing --remote --build "$APP_PATH"
timeoutInMinutes: 20
displayName: Run smoke tests (Remote)
- script: |
set -e
ps -ef
cat /proc/sys/fs/inotify/max_user_watches
lsof | wc -l
displayName: Diagnostics after smoke test run (processes, max_user_watches, number of opened file handles)
continueOnError: true
condition: succeededOrFailed()
- ${{ if or(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
- task: ${{ parameters.PUBLISH_TASK_NAME }}
inputs:
targetPath: .build/crashes
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: crash-dump-linux-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: crash-dump-linux-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: crash-dump-linux-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Crash Reports"
continueOnError: true
condition: failed()
# In order to properly symbolify above crash reports
# (if any), we need the compiled native modules too
- task: ${{ parameters.PUBLISH_TASK_NAME }}
inputs:
targetPath: node_modules
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: node-modules-linux-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: node-modules-linux-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: node-modules-linux-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Node Modules"
continueOnError: true
condition: failed()
- task: ${{ parameters.PUBLISH_TASK_NAME }}
inputs:
targetPath: .build/logs
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: logs-linux-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: logs-linux-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: logs-linux-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Log Files"
continueOnError: true
condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
testResultsFiles: "*-results.xml"
searchFolder: "$(Build.ArtifactStagingDirectory)/test-results"
condition: succeededOrFailed()
================================================
FILE: build/azure-pipelines/linux/product-build-linux.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_CIBUILD
type: boolean
- name: VSCODE_RUN_UNIT_TESTS
type: boolean
- name: VSCODE_RUN_INTEGRATION_TESTS
type: boolean
- name: VSCODE_RUN_SMOKE_TESTS
type: boolean
- name: VSCODE_ARCH
type: string
steps:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- checkout: self
fetchDepth: 1
retryCountOnTaskFailure: 3
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- task: DownloadPipelineArtifact@2
inputs:
artifact: Compilation
path: $(Build.ArtifactStagingDirectory)
displayName: Download compilation output
- script: tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
displayName: Extract compilation output
- script: |
set -e
# Start X server
./build/azure-pipelines/linux/apt-retry.sh sudo apt-get update
./build/azure-pipelines/linux/apt-retry.sh sudo apt-get install -y pkg-config \
dbus \
xvfb \
libgtk-3-0 \
libxkbfile-dev \
libkrb5-dev \
libgbm1 \
rpm
sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
sudo chmod +x /etc/init.d/xvfb
sudo update-rc.d xvfb defaults
sudo service xvfb start
# Start dbus session
sudo mkdir -p /var/run/dbus
DBUS_LAUNCH_RESULT=$(sudo dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address)
echo "##vso[task.setvariable variable=DBUS_SESSION_BUS_ADDRESS]$DBUS_LAUNCH_RESULT"
displayName: Setup system services
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js linux $VSCODE_ARCH > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- script: tar -xzf .build/node_modules_cache/cache.tgz
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install build dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
# Step will be used by both Install dependencies and building rpm package,
# hence avoid adding it behind NODE_MODULES_RESTORED condition.
- script: |
set -e
SYSROOT_ARCH=$VSCODE_ARCH
if [ "$SYSROOT_ARCH" == "x64" ]; then
SYSROOT_ARCH="amd64"
fi
export VSCODE_SYSROOT_DIR=$(Build.SourcesDirectory)/.build/sysroots
SYSROOT_ARCH="$SYSROOT_ARCH" node -e '(async () => { const { getVSCodeSysroot } = require("./build/linux/debian/install-sysroot.js"); await getVSCodeSysroot(process.env["SYSROOT_ARCH"]); })()'
env:
VSCODE_ARCH: $(VSCODE_ARCH)
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Download vscode sysroots
- ${{ if or(eq(parameters.VSCODE_ARCH, 'arm64'), eq(parameters.VSCODE_ARCH, 'armhf')) }}:
- script: |
set -e
includes=$(cat << 'EOF'
{
"target_defaults": {
"conditions": [
["OS=='linux'", {
'cflags_cc!': [ '-std=gnu++20' ],
'cflags_cc': [ '-std=gnu++2a' ],
}]
]
}
}
EOF
)
if [ ! -d "$HOME/.gyp" ]; then
mkdir -p "$HOME/.gyp"
fi
echo "$includes" > "$HOME/.gyp/include.gypi"
displayName: Override gnu target for arm64 and arm
- script: |
set -e
source ./build/azure-pipelines/linux/setup-env.sh
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
env:
npm_config_arch: $(NPM_ARCH)
VSCODE_ARCH: $(VSCODE_ARCH)
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/azure-pipelines/distro/mixin-npm
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Mixin distro node modules
- script: |
set -e
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
mkdir -p .build/node_modules_cache
tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- template: ../common/install-builtin-extensions.yml@self
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
set -e
npm run gulp vscode-linux-$(VSCODE_ARCH)-min-ci
ARCHIVE_PATH=".build/linux/client/code-${{ parameters.VSCODE_QUALITY }}-$(VSCODE_ARCH)-$(date +%s).tar.gz"
mkdir -p $(dirname $ARCHIVE_PATH)
echo "##vso[task.setvariable variable=CLIENT_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build client
- ${{ if ne(parameters.VSCODE_CIBUILD, true) }}:
- task: DownloadPipelineArtifact@2
inputs:
artifact: $(ARTIFACT_PREFIX)vscode_cli_linux_$(VSCODE_ARCH)_cli
patterns: "**"
path: $(Build.ArtifactStagingDirectory)/cli
displayName: Download VS Code CLI
- script: |
set -e
tar -xzvf $(Build.ArtifactStagingDirectory)/cli/*.tar.gz -C $(Build.ArtifactStagingDirectory)/cli
CLI_APP_NAME=$(node -p "require(\"$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)/resources/app/product.json\").tunnelApplicationName")
APP_NAME=$(node -p "require(\"$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)/resources/app/product.json\").applicationName")
mv $(Build.ArtifactStagingDirectory)/cli/$APP_NAME $(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)/bin/$CLI_APP_NAME
displayName: Mix in CLI
- script: |
set -e
tar -czf $CLIENT_PATH -C .. VSCode-linux-$(VSCODE_ARCH)
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Archive client
- script: |
set -e
npm run gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci
mv ../vscode-reh-linux-$(VSCODE_ARCH) ../vscode-server-linux-$(VSCODE_ARCH) # TODO@joaomoreno
ARCHIVE_PATH=".build/linux/server/vscode-server-linux-$(VSCODE_ARCH).tar.gz"
UNARCHIVE_PATH="`pwd`/../vscode-server-linux-$(VSCODE_ARCH)"
mkdir -p $(dirname $ARCHIVE_PATH)
tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-server-linux-$(VSCODE_ARCH)
echo "##vso[task.setvariable variable=SERVER_PATH]$ARCHIVE_PATH"
echo "##vso[task.setvariable variable=SERVER_UNARCHIVE_PATH]$UNARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server
- script: |
set -e
npm run gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci
mv ../vscode-reh-web-linux-$(VSCODE_ARCH) ../vscode-server-linux-$(VSCODE_ARCH)-web # TODO@joaomoreno
ARCHIVE_PATH=".build/linux/web/vscode-server-linux-$(VSCODE_ARCH)-web.tar.gz"
mkdir -p $(dirname $ARCHIVE_PATH)
tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-server-linux-$(VSCODE_ARCH)-web
echo "##vso[task.setvariable variable=WEB_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server (web)
- ${{ if or(eq(parameters.VSCODE_ARCH, 'x64'), eq(parameters.VSCODE_ARCH, 'arm64')) }}:
- script: |
set -e
EXPECTED_GLIBC_VERSION="2.28" \
EXPECTED_GLIBCXX_VERSION="3.4.25" \
./build/azure-pipelines/linux/verify-glibc-requirements.sh
env:
SEARCH_PATH: $(SERVER_UNARCHIVE_PATH)
npm_config_arch: $(NPM_ARCH)
VSCODE_ARCH: $(VSCODE_ARCH)
displayName: Check GLIBC and GLIBCXX dependencies in server archive
- ${{ else }}:
- script: |
set -e
EXPECTED_GLIBC_VERSION="2.28" \
EXPECTED_GLIBCXX_VERSION="3.4.26" \
./build/azure-pipelines/linux/verify-glibc-requirements.sh
env:
SEARCH_PATH: $(SERVER_UNARCHIVE_PATH)
npm_config_arch: $(NPM_ARCH)
VSCODE_ARCH: $(VSCODE_ARCH)
displayName: Check GLIBC and GLIBCXX dependencies in server archive
- ${{ else }}:
- script: npm run gulp "transpile-client-esbuild" "transpile-extensions"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Transpile client and extensions
- ${{ if or(eq(parameters.VSCODE_RUN_UNIT_TESTS, true), eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
- template: product-build-linux-test.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_RUN_UNIT_TESTS: ${{ parameters.VSCODE_RUN_UNIT_TESTS }}
VSCODE_RUN_INTEGRATION_TESTS: ${{ parameters.VSCODE_RUN_INTEGRATION_TESTS }}
VSCODE_RUN_SMOKE_TESTS: ${{ parameters.VSCODE_RUN_SMOKE_TESTS }}
${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
PUBLISH_TASK_NAME: 1ES.PublishPipelineArtifact@1
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'oss')) }}:
- script: |
set -e
npm run gulp "vscode-linux-$(VSCODE_ARCH)-prepare-deb"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Prepare deb package
- script: |
set -e
npm run gulp "vscode-linux-$(VSCODE_ARCH)-build-deb"
file_output=$(file $(ls .build/linux/deb/*/deb/*.deb))
if [[ "$file_output" != *"data compression xz"* ]]; then
echo "Error: unknown compression. $file_output"
exit 1
fi
echo "##vso[task.setvariable variable=DEB_PATH]$(ls .build/linux/deb/*/deb/*.deb)"
displayName: Build deb package
- script: |
set -e
TRIPLE=""
if [ "$VSCODE_ARCH" == "x64" ]; then
TRIPLE="x86_64-linux-gnu"
elif [ "$VSCODE_ARCH" == "arm64" ]; then
TRIPLE="aarch64-linux-gnu"
elif [ "$VSCODE_ARCH" == "armhf" ]; then
TRIPLE="arm-rpi-linux-gnueabihf"
fi
export VSCODE_SYSROOT_DIR=$(Build.SourcesDirectory)/.build/sysroots
export STRIP="$VSCODE_SYSROOT_DIR/$TRIPLE/$TRIPLE/bin/strip"
npm run gulp "vscode-linux-$(VSCODE_ARCH)-prepare-rpm"
env:
VSCODE_ARCH: $(VSCODE_ARCH)
displayName: Prepare rpm package
- script: |
set -e
npm run gulp "vscode-linux-$(VSCODE_ARCH)-build-rpm"
echo "##vso[task.setvariable variable=RPM_PATH]$(ls .build/linux/rpm/*/*.rpm)"
displayName: Build rpm package
- script: |
set -e
npm run gulp "vscode-linux-$(VSCODE_ARCH)-prepare-snap"
ARCHIVE_PATH=".build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz"
mkdir -p $(dirname $ARCHIVE_PATH)
tar -czf $ARCHIVE_PATH -C .build/linux snap
echo "##vso[task.setvariable variable=SNAP_PATH]$ARCHIVE_PATH"
displayName: Prepare snap package
- task: UseDotNet@2
inputs:
version: 6.x
- task: EsrpCodeSigning@5
inputs:
UseMSIAuthentication: true
ConnectedServiceName: vscode-esrp
AppRegistrationClientId: $(ESRP_CLIENT_ID)
AppRegistrationTenantId: $(ESRP_TENANT_ID)
AuthAKVName: vscode-esrp
AuthSignCertName: esrp-sign
FolderPath: .
Pattern: noop
displayName: 'Install ESRP Tooling'
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll sign-pgp .build/linux/deb '*.deb'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign deb
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll sign-pgp .build/linux/rpm '*.rpm'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign rpm
- script: echo "##vso[task.setvariable variable=ARTIFACT_PREFIX]attempt$(System.JobAttempt)_"
condition: and(succeededOrFailed(), notIn(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues'))
displayName: Generate artifact prefix
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(CLIENT_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_client_linux_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-linux-$(VSCODE_ARCH)
sbomPackageName: "VS Code Linux $(VSCODE_ARCH) (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['CLIENT_PATH'], ''))
displayName: Publish client archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SERVER_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_server_linux_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-linux-$(VSCODE_ARCH)
sbomPackageName: "VS Code Linux $(VSCODE_ARCH) Server"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['SERVER_PATH'], ''))
displayName: Publish server archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(WEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_web_linux_$(VSCODE_ARCH)_archive-unsigned
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-linux-$(VSCODE_ARCH)-web
sbomPackageName: "VS Code Linux $(VSCODE_ARCH) Web"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], ''))
displayName: Publish web server archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(DEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_client_linux_$(VSCODE_ARCH)_deb-package
sbomBuildDropPath: .build/linux/deb
sbomPackageName: "VS Code Linux $(VSCODE_ARCH) DEB"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['DEB_PATH'], ''))
displayName: Publish deb package
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(RPM_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_client_linux_$(VSCODE_ARCH)_rpm-package
sbomBuildDropPath: .build/linux/rpm
sbomPackageName: "VS Code Linux $(VSCODE_ARCH) RPM"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['RPM_PATH'], ''))
displayName: Publish rpm package
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SNAP_PATH)
artifactName: $(ARTIFACT_PREFIX)snap-$(VSCODE_ARCH)
sbomEnabled: false
condition: and(succeededOrFailed(), ne(variables['SNAP_PATH'], ''))
displayName: Publish snap pre-package
================================================
FILE: build/azure-pipelines/linux/setup-env.sh
================================================
#!/usr/bin/env bash
set -e
SYSROOT_ARCH=$VSCODE_ARCH
if [ "$SYSROOT_ARCH" == "x64" ]; then
SYSROOT_ARCH="amd64"
fi
export VSCODE_SYSROOT_DIR=$PWD/.build/sysroots
if [ -d "$VSCODE_SYSROOT_DIR" ]; then
echo "Using cached sysroot"
else
echo "Downloading sysroot"
SYSROOT_ARCH="$SYSROOT_ARCH" node -e '(async () => { const { getVSCodeSysroot } = require("./build/linux/debian/install-sysroot.js"); await getVSCodeSysroot(process.env["SYSROOT_ARCH"]); })()'
fi
if [ "$npm_config_arch" == "x64" ]; then
# Download clang based on chromium revision used by vscode
curl -s https://raw.githubusercontent.com/chromium/chromium/132.0.6834.210/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 \
VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \
VSCODE_LIBCXX_HEADERS_DIR=$PWD/.build/libcxx_headers \
VSCODE_LIBCXXABI_HEADERS_DIR=$PWD/.build/libcxxabi_headers \
VSCODE_ARCH="$npm_config_arch" \
node build/linux/libcxx-fetcher.js
# Set compiler toolchain
# Flags for the client build are based on
# https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:build/config/arm.gni
# https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:build/config/compiler/BUILD.gn
# https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:build/config/c++/BUILD.gn
export CC="$PWD/.build/CR_Clang/bin/clang --gcc-toolchain=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu"
export CXX="$PWD/.build/CR_Clang/bin/clang++ --gcc-toolchain=$VSCODE_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_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot"
export LDFLAGS="-stdlib=libc++ --sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -fuse-ld=lld -flto=thin -L$PWD/.build/libcxx-objects -lc++abi -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/x86_64-linux-gnu -Wl,--lto-O0"
# Set compiler toolchain for remote server
export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc
export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-g++
export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot"
export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/x86_64-linux-gnu"
elif [ "$npm_config_arch" == "arm64" ]; then
# Set compiler toolchain for client native modules
export CC=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
export CXX=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
export CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot"
export LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/lib/aarch64-linux-gnu"
# Set compiler toolchain for remote server
export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot"
export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/lib/aarch64-linux-gnu"
elif [ "$npm_config_arch" == "arm" ]; then
# Set compiler toolchain for client native modules
export CC=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc
export CXX=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-g++
export CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot"
export LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/lib/arm-linux-gnueabihf"
# Set compiler toolchain for remote server
export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc
export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-g++
export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot"
export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/lib/arm-linux-gnueabihf"
fi
================================================
FILE: build/azure-pipelines/linux/snap-build-linux.yml
================================================
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- task: DownloadPipelineArtifact@2
displayName: "Download Pipeline Artifact"
inputs:
artifact: snap-$(VSCODE_ARCH)
path: .build/linux/snap-tarball
- script: |
set -e
# Get snapcraft version
snapcraft --version
# Make sure we get latest packages
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y curl apt-transport-https ca-certificates
# Define variables
SNAP_ROOT="$(pwd)/.build/linux/snap/$(VSCODE_ARCH)"
# Unpack snap tarball artifact, in order to preserve file perms
(cd .build/linux && tar -xzf snap-tarball/snap-$(VSCODE_ARCH).tar.gz)
# Create snap package
BUILD_VERSION="$(date +%s)"
SNAP_FILENAME="code-$VSCODE_QUALITY-$(VSCODE_ARCH)-$BUILD_VERSION.snap"
SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME"
case $(VSCODE_ARCH) in
x64) SNAPCRAFT_TARGET_ARGS="" ;;
*) SNAPCRAFT_TARGET_ARGS="--target-arch $(VSCODE_ARCH)" ;;
esac
(cd $SNAP_ROOT/code-* && sudo --preserve-env snapcraft snap $SNAPCRAFT_TARGET_ARGS --output "$SNAP_PATH")
displayName: Prepare for publish
- script: |
set -e
SNAP_ROOT="$(pwd)/.build/linux/snap/$(VSCODE_ARCH)"
SNAP_EXTRACTED_PATH=$(find $SNAP_ROOT -maxdepth 1 -type d -name 'code-*')
SNAP_PATH=$(find $SNAP_ROOT -maxdepth 1 -type f -name '*.snap')
# SBOM tool doesn't like recursive symlinks
sudo find $SNAP_EXTRACTED_PATH -type l -delete
echo "##vso[task.setvariable variable=SNAP_EXTRACTED_PATH]$SNAP_EXTRACTED_PATH"
echo "##vso[task.setvariable variable=SNAP_PATH]$SNAP_PATH"
target:
container: host
displayName: Find host snap path & prepare for SBOM
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SNAP_PATH)
artifactName: vscode_client_linux_$(VSCODE_ARCH)_snap
sbomBuildDropPath: $(SNAP_EXTRACTED_PATH)
sbomPackageName: "VS Code Linux $(VSCODE_ARCH) SNAP"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish snap package
================================================
FILE: build/azure-pipelines/linux/verify-glibc-requirements.sh
================================================
#!/usr/bin/env bash
set -e
TRIPLE="x86_64-linux-gnu"
if [ "$VSCODE_ARCH" == "arm64" ]; then
TRIPLE="aarch64-linux-gnu"
elif [ "$VSCODE_ARCH" == "armhf" ]; then
TRIPLE="arm-rpi-linux-gnueabihf"
fi
# Get all files with .node extension from server folder
files=$(find $SEARCH_PATH -name "*.node" -not -path "*prebuilds*" -not -path "*extensions/node_modules/@parcel/watcher*" -o -type f -executable -name "node")
echo "Verifying requirements for files: $files"
for file in $files; do
glibc_version="$EXPECTED_GLIBC_VERSION"
glibcxx_version="$EXPECTED_GLIBCXX_VERSION"
while IFS= read -r line; do
if [[ $line == *"GLIBC_"* ]]; then
version=$(echo "$line" | awk '{if ($5 ~ /^[0-9a-fA-F]+$/) print $6; else print $5}' | tr -d '()')
version=${version#*_}
if [[ $(printf "%s\n%s" "$version" "$glibc_version" | sort -V | tail -n1) == "$version" ]]; then
glibc_version=$version
fi
elif [[ $line == *"GLIBCXX_"* ]]; then
version=$(echo "$line" | awk '{if ($5 ~ /^[0-9a-fA-F]+$/) print $6; else print $5}' | tr -d '()')
version=${version#*_}
if [[ $(printf "%s\n%s" "$version" "$glibcxx_version" | sort -V | tail -n1) == "$version" ]]; then
glibcxx_version=$version
fi
fi
done < <("$PWD/.build/sysroots/$TRIPLE/$TRIPLE/bin/objdump" -T "$file")
if [[ "$glibc_version" != "$EXPECTED_GLIBC_VERSION" ]]; then
echo "Error: File $file has dependency on GLIBC > $EXPECTED_GLIBC_VERSION, found $glibc_version"
exit 1
fi
if [[ "$glibcxx_version" != "$EXPECTED_GLIBCXX_VERSION" ]]; then
echo "Error: File $file has dependency on GLIBCXX > $EXPECTED_GLIBCXX_VERSION, found $glibcxx_version"
exit 1
fi
done
================================================
FILE: build/azure-pipelines/linux/xvfb.init
================================================
#!/bin/bash
#
# /etc/rc.d/init.d/xvfbd
#
# chkconfig: 345 95 28
# description: Starts/Stops X Virtual Framebuffer server
# processname: Xvfb
#
### BEGIN INIT INFO
# Provides: xvfb
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start xvfb at boot time
# Description: Enable xvfb provided by daemon.
### END INIT INFO
[ "${NETWORKING}" = "no" ] && exit 0
PROG="/usr/bin/Xvfb"
PROG_OPTIONS=":10 -ac -screen 0 1024x768x24"
PROG_OUTPUT="/tmp/Xvfb.out"
case "$1" in
start)
echo "Starting : X Virtual Frame Buffer "
$PROG $PROG_OPTIONS>>$PROG_OUTPUT 2>&1 &
disown -ar
;;
stop)
echo "Shutting down : X Virtual Frame Buffer"
killproc $PROG
RETVAL=$?
[ $RETVAL -eq 0 ] && /bin/rm -f /var/lock/subsys/Xvfb
/var/run/Xvfb.pid
echo
;;
restart|reload)
$0 stop
$0 start
RETVAL=$?
;;
status)
status Xvfb
RETVAL=$?
;;
*)
echo $"Usage: $0 (start|stop|restart|reload|status)"
exit 1
esac
exit $RETVAL
================================================
FILE: build/azure-pipelines/oss/product-build-pr-cache-linux.yml
================================================
steps:
- checkout: self
fetchDepth: 1
retryCountOnTaskFailure: 3
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js linux $VSCODE_ARCH > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- script: tar -xzf .build/node_modules_cache/cache.tgz
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
./build/azure-pipelines/linux/apt-retry.sh sudo apt-get update
./build/azure-pipelines/linux/apt-retry.sh sudo apt-get install -y libkrb5-dev
displayName: Setup system services
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
env:
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: |
set -e
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
mkdir -p .build/node_modules_cache
tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
================================================
FILE: build/azure-pipelines/oss/product-build-pr-cache-win32.yml
================================================
steps:
- checkout: self
fetchDepth: 1
retryCountOnTaskFailure: 3
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- powershell: node build/setup-npm-registry.js $env:NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- pwsh: |
mkdir .build -ea 0
node build/azure-pipelines/common/computeNodeModulesCacheKey.js win32 $(VSCODE_ARCH) > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- powershell: 7z.exe x .build/node_modules_cache/cache.7z -aoa
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
exec { npm config set registry "$env:NPM_REGISTRY" }
$NpmrcPath = (npm config get userconfig)
echo "##vso[task.setvariable variable=NPMRC_PATH]$NpmrcPath"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm ci }
env:
npm_config_arch: $(VSCODE_ARCH)
npm_config_foreground_scripts: "true"
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
retryCountOnTaskFailure: 5
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt }
exec { mkdir -Force .build/node_modules_cache }
exec { 7z.exe a .build/node_modules_cache/cache.7z -mx3 `@.build/node_modules_list.txt }
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
================================================
FILE: build/azure-pipelines/product-build-pr.yml
================================================
trigger:
- main
- release/*
pr:
branches:
include: ["main", "release/*"]
variables:
- name: Codeql.SkipTaskAutoInjection
value: true
- name: skipComponentGovernanceDetection
value: true
- name: NPM_REGISTRY
value: "none"
- name: CARGO_REGISTRY
value: "none"
- name: VSCODE_CIBUILD
value: ${{ in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') }}
- name: VSCODE_QUALITY
value: oss
- name: VSCODE_STEP_ON_IT
value: false
jobs:
- ${{ if ne(variables['VSCODE_CIBUILD'], true) }}:
- job: Compile
displayName: Compile & Hygiene
pool: 1es-oss-ubuntu-22.04-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
steps:
- template: product-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
- job: Linuxx64UnitTest
displayName: Linux (Unit Tests)
pool: 1es-oss-ubuntu-22.04-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: true
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- job: Linuxx64IntegrationTest
displayName: Linux (Integration Tests)
pool: 1es-oss-ubuntu-22.04-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: true
VSCODE_RUN_SMOKE_TESTS: false
- job: Linuxx64SmokeTest
displayName: Linux (Smoke Tests)
pool: 1es-oss-ubuntu-22.04-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: true
- job: LinuxCLI
displayName: Linux (CLI)
pool: 1es-oss-ubuntu-22.04-x64
timeoutInMinutes: 30
steps:
- template: cli/test.yml@self
- job: Windowsx64UnitTests
displayName: Windows (Unit Tests)
pool: 1es-oss-windows-2022-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
steps:
- template: win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: x64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: true
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- job: Windowsx64IntegrationTests
displayName: Windows (Integration Tests)
pool: 1es-oss-windows-2022-x64
timeoutInMinutes: 60
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
steps:
- template: win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: x64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: true
VSCODE_RUN_SMOKE_TESTS: false
# - job: Windowsx64SmokeTests
# displayName: Windows (Smoke Tests)
# pool: 1es-oss-windows-2022-x64
# timeoutInMinutes: 30
# variables:
# VSCODE_ARCH: x64
# NPM_ARCH: x64
# steps:
# - template: win32/product-build-win32.yml@self
# parameters:
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
# VSCODE_ARCH: x64
# VSCODE_RUN_UNIT_TESTS: false
# VSCODE_RUN_INTEGRATION_TESTS: false
# VSCODE_RUN_SMOKE_TESTS: true
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
- job: Linuxx64MaintainNodeModulesCache
displayName: Linux (Maintain node_modules cache)
pool: 1es-oss-ubuntu-22.04-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
steps:
- template: oss/product-build-pr-cache-linux.yml@self
- job: Windowsx64MaintainNodeModulesCache
displayName: Windows (Maintain node_modules cache)
pool: 1es-oss-windows-2022-x64
timeoutInMinutes: 30
variables:
VSCODE_ARCH: x64
steps:
- template: oss/product-build-pr-cache-win32.yml@self
# - job: macOSUnitTest
# displayName: macOS (Unit Tests)
# pool:
# vmImage: macOS-11
# timeoutInMinutes: 60
# variables:
# BUILDSECMON_OPT_IN: true
# VSCODE_ARCH: x64
# steps:
# - template: darwin/product-build-darwin.yml@self
# parameters:
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
# VSCODE_RUN_UNIT_TESTS: true
# VSCODE_RUN_INTEGRATION_TESTS: false
# VSCODE_RUN_SMOKE_TESTS: false
# - job: macOSIntegrationTest
# displayName: macOS (Integration Tests)
# pool:
# vmImage: macOS-11
# timeoutInMinutes: 60
# variables:
# BUILDSECMON_OPT_IN: true
# VSCODE_ARCH: x64
# steps:
# - template: darwin/product-build-darwin.yml@self
# parameters:
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
# VSCODE_RUN_UNIT_TESTS: false
# VSCODE_RUN_INTEGRATION_TESTS: true
# VSCODE_RUN_SMOKE_TESTS: false
# - job: macOSSmokeTest
# displayName: macOS (Smoke Tests)
# pool:
# vmImage: macOS-11
# timeoutInMinutes: 60
# variables:
# BUILDSECMON_OPT_IN: true
# VSCODE_ARCH: x64
# steps:
# - template: darwin/product-build-darwin.yml@self
# parameters:
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
# VSCODE_RUN_UNIT_TESTS: false
# VSCODE_RUN_INTEGRATION_TESTS: false
# VSCODE_RUN_SMOKE_TESTS: true
================================================
FILE: build/azure-pipelines/product-build.yml
================================================
pr: none
schedules:
- cron: "0 5 * * Mon-Fri"
displayName: Mon-Fri at 7:00
branches:
include:
- main
trigger:
batch: true
branches:
include: ["main", "release/*"]
parameters:
- name: VSCODE_QUALITY
displayName: Quality
type: string
default: insider
values:
- exploration
- insider
- stable
- name: NPM_REGISTRY
displayName: "Custom NPM Registry"
type: string
default: 'https://pkgs.dev.azure.com/monacotools/Monaco/_packaging/vscode/npm/registry/'
- name: CARGO_REGISTRY
displayName: "Custom Cargo Registry"
type: string
default: 'sparse+https://pkgs.dev.azure.com/monacotools/Monaco/_packaging/vscode/Cargo/index/'
- name: VSCODE_BUILD_WIN32
displayName: "🎯 Windows x64"
type: boolean
default: true
- name: VSCODE_BUILD_WIN32_ARM64
displayName: "🎯 Windows arm64"
type: boolean
default: true
- name: VSCODE_BUILD_LINUX
displayName: "🎯 Linux x64"
type: boolean
default: true
- name: VSCODE_BUILD_LINUX_ARM64
displayName: "🎯 Linux arm64"
type: boolean
default: true
- name: VSCODE_BUILD_LINUX_ARMHF
displayName: "🎯 Linux armhf"
type: boolean
default: true
- name: VSCODE_BUILD_ALPINE
displayName: "🎯 Alpine x64"
type: boolean
default: true
- name: VSCODE_BUILD_ALPINE_ARM64
displayName: "🎯 Alpine arm64"
type: boolean
default: true
- name: VSCODE_BUILD_MACOS
displayName: "🎯 macOS x64"
type: boolean
default: true
- name: VSCODE_BUILD_MACOS_ARM64
displayName: "🎯 macOS arm64"
type: boolean
default: true
- name: VSCODE_BUILD_MACOS_UNIVERSAL
displayName: "🎯 macOS universal"
type: boolean
default: true
- name: VSCODE_BUILD_WEB
displayName: "🎯 Web"
type: boolean
default: true
- name: VSCODE_PUBLISH
displayName: "Publish to builds.code.visualstudio.com"
type: boolean
default: true
- name: VSCODE_RELEASE
displayName: "Release build if successful"
type: boolean
default: false
- name: VSCODE_COMPILE_ONLY
displayName: "Run Compile stage exclusively"
type: boolean
default: false
- name: VSCODE_STEP_ON_IT
displayName: "Skip tests"
type: boolean
default: false
variables:
- name: VSCODE_PRIVATE_BUILD
value: ${{ ne(variables['Build.Repository.Uri'], 'https://github.com/microsoft/vscode.git') }}
- name: NPM_REGISTRY
${{ if in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') }}: # disable terrapin when in VSCODE_CIBUILD
value: none
${{ else }}:
value: ${{ parameters.NPM_REGISTRY }}
- name: CARGO_REGISTRY
value: ${{ parameters.CARGO_REGISTRY }}
- name: VSCODE_QUALITY
value: ${{ parameters.VSCODE_QUALITY }}
- name: VSCODE_BUILD_STAGE_WINDOWS
value: ${{ or(eq(parameters.VSCODE_BUILD_WIN32, true), eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }}
- name: VSCODE_BUILD_STAGE_LINUX
value: ${{ or(eq(parameters.VSCODE_BUILD_LINUX, true), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }}
- name: VSCODE_BUILD_STAGE_ALPINE
value: ${{ or(eq(parameters.VSCODE_BUILD_ALPINE, true), eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true)) }}
- name: VSCODE_BUILD_STAGE_MACOS
value: ${{ or(eq(parameters.VSCODE_BUILD_MACOS, true), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true)) }}
- name: VSCODE_BUILD_STAGE_WEB
value: ${{ eq(parameters.VSCODE_BUILD_WEB, true) }}
- name: VSCODE_CIBUILD
value: ${{ in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') }}
- name: VSCODE_PUBLISH
value: ${{ and(eq(parameters.VSCODE_PUBLISH, true), eq(variables.VSCODE_CIBUILD, false), eq(parameters.VSCODE_COMPILE_ONLY, false)) }}
- name: VSCODE_SCHEDULEDBUILD
value: ${{ eq(variables['Build.Reason'], 'Schedule') }}
- name: VSCODE_STEP_ON_IT
value: ${{ eq(parameters.VSCODE_STEP_ON_IT, true) }}
- name: VSCODE_BUILD_MACOS_UNIVERSAL
value: ${{ and(eq(parameters.VSCODE_BUILD_MACOS, true), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true), eq(parameters.VSCODE_BUILD_MACOS_UNIVERSAL, true)) }}
- name: VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME
value: vscodeesrp
- name: PRSS_CDN_URL
value: https://vscode.download.prss.microsoft.com/dbazure/download
- name: VSCODE_ESRP_SERVICE_CONNECTION_ID
value: fe07e6ce-6ffb-4df9-8d27-d129523a3f3e
- name: VSCODE_ESRP_TENANT_ID
value: 975f013f-7f24-47e8-a7d3-abc4752bf346
- name: VSCODE_ESRP_CLIENT_ID
value: 4ac7ed59-b5e9-4f66-9c30-8d1afa72d32d
- name: ESRP_TENANT_ID
value: 975f013f-7f24-47e8-a7d3-abc4752bf346
- name: ESRP_CLIENT_ID
value: c24324f7-e65f-4c45-8702-ed2d4c35df99
- name: AZURE_DOCUMENTDB_ENDPOINT
value: https://vscode.documents.azure.com/
- name: VSCODE_MIXIN_REPO
value: microsoft/vscode-distro
- name: skipComponentGovernanceDetection
value: true
- name: ComponentDetection.Timeout
value: 600
- name: Codeql.SkipTaskAutoInjection
value: true
- name: ARTIFACT_PREFIX
value: ''
name: "$(Date:yyyyMMdd).$(Rev:r) (${{ parameters.VSCODE_QUALITY }})"
resources:
pipelines:
- pipeline: vscode-7pm-kick-off
source: 'VS Code 7PM Kick-Off'
trigger: true
repositories:
- repository: 1ESPipelines
type: git
name: 1ESPipelineTemplates/1ESPipelineTemplates
ref: refs/tags/release
extends:
template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines
parameters:
sdl:
tsa:
enabled: true
configFile: $(Build.SourcesDirectory)/build/azure-pipelines/config/tsaoptions.json
binskim:
analyzeTargetGlob: '+:file|$(Agent.BuildDirectory)/VSCode-*/**/*.exe;+:file|$(Agent.BuildDirectory)/VSCode-*/**/*.node;+:file|$(Agent.BuildDirectory)/VSCode-*/**/*.dll;-:file|$(Build.SourcesDirectory)/.build/**/system-setup/VSCodeSetup*.exe;-:file|$(Build.SourcesDirectory)/.build/**/user-setup/VSCodeUserSetup*.exe'
codeql:
runSourceLanguagesInSourceAnalysis: true
compiled:
enabled: false
justificationForDisabling: "CodeQL breaks ESRP CodeSign on macOS (ICM #520035761, githubcustomers/microsoft-codeql-support#198)"
credscan:
suppressionsFile: $(Build.SourcesDirectory)/build/azure-pipelines/config/CredScanSuppressions.json
eslint:
enabled: true
enableExclusions: true
exclusionsFilePath: $(Build.SourcesDirectory)/.eslint-ignore
sourceAnalysisPool: 1es-windows-2022-x64
createAdoIssuesForJustificationsForDisablement: false
containers:
snapcraft:
image: vscodehub.azurecr.io/vscode-linux-build-agent:snapcraft-x64
ubuntu-2004-arm64:
image: onebranch.azurecr.io/linux/ubuntu-2004-arm64:latest
stages:
- stage: Compile
jobs:
- job: Compile
timeoutInMinutes: 90
pool:
name: AcesShared
os: macOS
variables:
VSCODE_ARCH: arm64
steps:
- template: build/azure-pipelines/product-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.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
dependsOn: []
jobs:
- ${{ if eq(parameters.VSCODE_BUILD_LINUX, true) }}:
- job: CLILinuxX64
pool:
name: 1es-ubuntu-22.04-x64
os: linux
steps:
- template: build/azure-pipelines/linux/cli-build-linux.yml@self
parameters:
VSCODE_CHECK_ONLY: ${{ variables.VSCODE_CIBUILD }}
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_LINUX: ${{ parameters.VSCODE_BUILD_LINUX }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), or(eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true))) }}:
- job: CLILinuxGnuARM
pool:
name: 1es-ubuntu-22.04-x64
os: linux
steps:
- template: build/azure-pipelines/linux/cli-build-linux.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_LINUX_ARMHF: ${{ parameters.VSCODE_BUILD_LINUX_ARMHF }}
VSCODE_BUILD_LINUX_ARM64: ${{ parameters.VSCODE_BUILD_LINUX_ARM64 }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_ALPINE, true)) }}:
- job: CLIAlpineX64
pool:
name: 1es-ubuntu-22.04-x64
os: linux
steps:
- template: build/azure-pipelines/alpine/cli-build-alpine.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_ALPINE: ${{ parameters.VSCODE_BUILD_ALPINE }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true)) }}:
- job: CLIAlpineARM64
pool:
name: 1es-mariner-2.0-arm64
os: linux
hostArchitecture: arm64
container: ubuntu-2004-arm64
templateContext:
authenticatedContainerRegistries:
- registry: onebranch.azurecr.io
tenant: AME
identity: 1ESPipelineIdentity
steps:
- template: build/azure-pipelines/alpine/cli-build-alpine.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_ALPINE_ARM64: ${{ parameters.VSCODE_BUILD_ALPINE_ARM64 }}
- ${{ if eq(parameters.VSCODE_BUILD_MACOS, true) }}:
- job: CLIMacOSX64
pool:
name: Azure Pipelines
image: macOS-13
os: macOS
variables:
# todo@connor4312 to diagnose build flakes
- name: MSRUSTUP_LOG
value: debug
steps:
- template: build/azure-pipelines/darwin/cli-build-darwin.yml@self
parameters:
VSCODE_CHECK_ONLY: ${{ variables.VSCODE_CIBUILD }}
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_MACOS: ${{ parameters.VSCODE_BUILD_MACOS }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true)) }}:
- job: CLIMacOSARM64
pool:
name: Azure Pipelines
image: macOS-13
os: macOS
variables:
# todo@connor4312 to diagnose build flakes
- name: MSRUSTUP_LOG
value: debug
steps:
- template: build/azure-pipelines/darwin/cli-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_MACOS_ARM64: ${{ parameters.VSCODE_BUILD_MACOS_ARM64 }}
- ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
- job: CLIWindowsX64
pool:
name: 1es-windows-2019-x64
os: windows
steps:
- template: build/azure-pipelines/win32/cli-build-win32.yml@self
parameters:
VSCODE_CHECK_ONLY: ${{ variables.VSCODE_CIBUILD }}
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_WIN32: ${{ parameters.VSCODE_BUILD_WIN32 }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }}:
- job: CLIWindowsARM64
pool:
name: 1es-windows-2019-x64
os: windows
steps:
- template: build/azure-pipelines/win32/cli-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_WIN32_ARM64: ${{ parameters.VSCODE_BUILD_WIN32_ARM64 }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_COMPILE_ONLY, false)) }}:
- stage: APIScan
dependsOn: []
pool:
name: 1es-windows-2019-x64
os: windows
jobs:
- job: WindowsAPIScan
steps:
- template: build/azure-pipelines/win32/sdl-scan-win32.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
- ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_WINDOWS'], true)) }}:
- stage: Windows
dependsOn:
- Compile
- ${{ 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)) }}:
- CompileCLI
pool:
name: 1es-windows-2019-x64
os: windows
jobs:
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
- job: WindowsUnitTests
displayName: Unit Tests
timeoutInMinutes: 60
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: x64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: true
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- job: WindowsIntegrationTests
displayName: Integration Tests
timeoutInMinutes: 60
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: x64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: true
VSCODE_RUN_SMOKE_TESTS: false
- job: WindowsSmokeTests
displayName: Smoke Tests
timeoutInMinutes: 60
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: x64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: true
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32, true)) }}:
- job: Windows
timeoutInMinutes: 120
variables:
VSCODE_ARCH: x64
templateContext:
sdl:
suppression:
suppressionFile: $(Build.SourcesDirectory)\.config\guardian\.gdnsuppress
steps:
- template: build/azure-pipelines/win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: x64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
VSCODE_RUN_INTEGRATION_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
VSCODE_RUN_SMOKE_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
- job: WindowsCLISign
timeoutInMinutes: 90
steps:
- template: build/azure-pipelines/win32/product-build-win32-cli-sign.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_WIN32: ${{ parameters.VSCODE_BUILD_WIN32 }}
VSCODE_BUILD_WIN32_ARM64: ${{ parameters.VSCODE_BUILD_WIN32_ARM64 }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }}:
- job: WindowsARM64
timeoutInMinutes: 90
variables:
VSCODE_ARCH: arm64
templateContext:
sdl:
suppression:
suppressionFile: $(Build.SourcesDirectory)\.config\guardian\.gdnsuppress
steps:
- template: build/azure-pipelines/win32/product-build-win32.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_ARCH: arm64
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_LINUX'], true)) }}:
- stage: Linux
dependsOn:
- Compile
- ${{ 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)) }}:
- CompileCLI
pool:
name: 1es-ubuntu-22.04-x64
os: linux
jobs:
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
- job: Linuxx64UnitTest
displayName: Unit Tests
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: build/azure-pipelines/linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: true
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- job: Linuxx64IntegrationTest
displayName: Integration Tests
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: build/azure-pipelines/linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: true
VSCODE_RUN_SMOKE_TESTS: false
- job: Linuxx64SmokeTest
displayName: Smoke Tests
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: build/azure-pipelines/linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: true
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX, true)) }}:
- job: Linuxx64
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
DISPLAY: ":10"
steps:
- template: build/azure-pipelines/linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: x64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
VSCODE_RUN_INTEGRATION_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
VSCODE_RUN_SMOKE_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX, true)) }}:
- job: LinuxSnap
dependsOn:
- Linuxx64
container: snapcraft
variables:
VSCODE_ARCH: x64
templateContext:
authenticatedContainerRegistries:
- registry: onebranch.azurecr.io
tenant: AME
identity: 1ESPipelineIdentity
steps:
- template: build/azure-pipelines/linux/snap-build-linux.yml@self
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true)) }}:
- job: LinuxArmhf
variables:
VSCODE_ARCH: armhf
NPM_ARCH: arm
steps:
- template: build/azure-pipelines/linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: armhf
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }}:
- job: LinuxArm64
variables:
VSCODE_ARCH: arm64
NPM_ARCH: arm64
steps:
- template: build/azure-pipelines/linux/product-build-linux.yml@self
parameters:
VSCODE_ARCH: arm64
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_ALPINE'], true)) }}:
- stage: Alpine
dependsOn:
- Compile
- ${{ 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)) }}:
- CompileCLI
pool:
name: 1es-ubuntu-22.04-x64
os: linux
jobs:
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE, true) }}:
- job: LinuxAlpine
variables:
VSCODE_ARCH: x64
NPM_ARCH: x64
steps:
- template: build/azure-pipelines/alpine/product-build-alpine.yml@self
- ${{ if eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true) }}:
- job: LinuxAlpineArm64
timeoutInMinutes: 120
variables:
VSCODE_ARCH: arm64
NPM_ARCH: arm64
steps:
- template: build/azure-pipelines/alpine/product-build-alpine.yml@self
- ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_MACOS'], true)) }}:
- stage: macOS
dependsOn:
- Compile
- ${{ 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)) }}:
- CompileCLI
pool:
name: Azure Pipelines
image: macOS-13
os: macOS
variables:
BUILDSECMON_OPT_IN: true
jobs:
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
- job: macOSUnitTest
displayName: Unit Tests
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: true
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- job: macOSIntegrationTest
displayName: Integration Tests
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: true
VSCODE_RUN_SMOKE_TESTS: false
- job: macOSSmokeTest
displayName: Smoke Tests
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: true
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS, true)) }}:
- job: macOS
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- ${{ if eq(parameters.VSCODE_STEP_ON_IT, false) }}:
- job: macOSTest
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
VSCODE_RUN_INTEGRATION_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
VSCODE_RUN_SMOKE_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }}
- job: macOSSign
dependsOn:
- macOS
timeoutInMinutes: 90
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin-sign.yml@self
- job: macOSCLISign
timeoutInMinutes: 90
steps:
- template: build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_BUILD_MACOS: ${{ parameters.VSCODE_BUILD_MACOS }}
VSCODE_BUILD_MACOS_ARM64: ${{ parameters.VSCODE_BUILD_MACOS_ARM64 }}
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true)) }}:
- job: macOSARM64
timeoutInMinutes: 90
variables:
VSCODE_ARCH: arm64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin.yml@self
parameters:
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }}
VSCODE_RUN_UNIT_TESTS: false
VSCODE_RUN_INTEGRATION_TESTS: false
VSCODE_RUN_SMOKE_TESTS: false
- job: macOSARM64Sign
dependsOn:
- macOSARM64
timeoutInMinutes: 90
variables:
VSCODE_ARCH: arm64
steps:
- template: build/azure-pipelines/darwin/product-build-darwin-sign.yml@self
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(variables['VSCODE_BUILD_MACOS_UNIVERSAL'], true)) }}:
- job: macOSUniversal
dependsOn:
- macOS
- macOSARM64
timeoutInMinutes: 90
variables:
VSCODE_ARCH: universal
steps:
- template: build/azure-pipelines/darwin/product-build-darwin-universal.yml@self
- job: macOSUniversalSign
dependsOn:
- macOSUniversal
timeoutInMinutes: 90
variables:
VSCODE_ARCH: universal
steps:
- template: build/azure-pipelines/darwin/product-build-darwin-sign.yml@self
- ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_WEB'], true)) }}:
- stage: Web
dependsOn:
- Compile
pool:
name: 1es-ubuntu-22.04-x64
os: linux
jobs:
- ${{ if eq(parameters.VSCODE_BUILD_WEB, true) }}:
- job: Web
variables:
VSCODE_ARCH: x64
steps:
- template: build/azure-pipelines/web/product-build-web.yml@self
- ${{ if eq(variables['VSCODE_PUBLISH'], 'true') }}:
- stage: Publish
dependsOn: []
pool:
name: 1es-windows-2019-x64
os: windows
variables:
- name: BUILDS_API_URL
value: $(System.CollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/
jobs:
- job: PublishBuild
timeoutInMinutes: 180
displayName: Publish Build
steps:
- template: build/azure-pipelines/product-publish.yml@self
- ${{ if and(parameters.VSCODE_RELEASE, eq(variables['VSCODE_PRIVATE_BUILD'], false)) }}:
- stage: ApproveRelease
dependsOn: [] # run in parallel to compile stage
pool:
name: 1es-ubuntu-22.04-x64
os: linux
jobs:
- job: ApproveRelease
displayName: "Approve Release"
variables:
- group: VSCodePeerApproval
- name: skipComponentGovernanceDetection
value: true
- ${{ if or(and(parameters.VSCODE_RELEASE, eq(variables['VSCODE_PRIVATE_BUILD'], false)), and(in(parameters.VSCODE_QUALITY, 'insider', 'exploration'), eq(variables['VSCODE_SCHEDULEDBUILD'], true))) }}:
- stage: Release
dependsOn:
- Publish
- ${{ if and(parameters.VSCODE_RELEASE, eq(variables['VSCODE_PRIVATE_BUILD'], false)) }}:
- ApproveRelease
pool:
name: 1es-ubuntu-22.04-x64
os: linux
jobs:
- job: ReleaseBuild
displayName: Release Build
steps:
- template: build/azure-pipelines/product-release.yml@self
parameters:
VSCODE_RELEASE: ${{ parameters.VSCODE_RELEASE }}
================================================
FILE: build/azure-pipelines/product-compile.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ./distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js compile $VSCODE_ARCH > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- script: tar -xzf .build/node_modules_cache/cache.tgz
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: sudo apt update -y && sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libnotify-bin libkrb5-dev
displayName: Install build tools
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
env:
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/azure-pipelines/distro/mixin-npm
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Mixin distro node modules
- script: |
set -e
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
mkdir -p .build/node_modules_cache
tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: npm run compile
workingDirectory: build
displayName: Compile /build/ folder
- script: .github/workflows/check-clean-git-state.sh
displayName: Check /build/ folder
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- template: common/install-builtin-extensions.yml@self
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- script: npm exec -- npm-run-all -lp core-ci-pr extensions-ci-pr hygiene eslint valid-layers-check property-init-order-check vscode-dts-compile-check tsec-compile-check
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Compile & Hygiene (OSS)
- ${{ else }}:
- script: npm exec -- npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check property-init-order-check vscode-dts-compile-check tsec-compile-check
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Compile & Hygiene (non-OSS)
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- script: |
set -e
npm run compile
displayName: Compile smoke test suites (non-OSS)
workingDirectory: test/smoke
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
npm run compile
displayName: Compile integration test suites (non-OSS)
workingDirectory: test/integration/browser
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- task: AzureCLI@2
displayName: Fetch secrets
inputs:
azureSubscription: vscode
scriptType: pscore
scriptLocation: inlineScript
addSpnToEnvironment: true
inlineScript: |
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken"
- script: |
set -e
AZURE_STORAGE_ACCOUNT="vscodeweb" \
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \
node build/azure-pipelines/upload-sourcemaps
displayName: Upload sourcemaps to Azure
- script: ./build/azure-pipelines/common/extract-telemetry.sh
displayName: Generate lists of telemetry events
- script: tar -cz --exclude='.build/node_modules_cache' --exclude='.build/node_modules_list.txt' --exclude='.build/distro' -f $(Build.ArtifactStagingDirectory)/compilation.tar.gz $(ls -d .build out-* test/integration/browser/out test/smoke/out test/automation/out 2>/dev/null)
displayName: Compress compilation artifact
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/compilation.tar.gz
artifactName: Compilation
sbomEnabled: false
displayName: Publish compilation artifact
- script: npm run download-builtin-extensions-cg
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Download component details of built-in extensions
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: "Component Detection"
inputs:
sourceScanPath: $(Build.SourcesDirectory)
alertWarningLevel: Medium
continueOnError: true
================================================
FILE: build/azure-pipelines/product-npm-package-validate.yml
================================================
trigger: none
pr:
branches:
include: ["main"]
paths:
include: ["package.json", "package-lock.json"]
variables:
- name: NPM_REGISTRY
value: "https://pkgs.dev.azure.com/monacotools/Monaco/_packaging/vscode/npm/registry/"
- name: VSCODE_CIBUILD
value: ${{ in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') }}
- name: VSCODE_QUALITY
value: oss
jobs:
- ${{ if ne(variables['VSCODE_CIBUILD'], true) }}:
- job: ValidateNpmPackage
displayName: Valiate NPM package against Terrapin
pool:
name: 1es-ubuntu-22.04-x64
os: linux
timeoutInMinutes: 40000
continueOnError: true
variables:
VSCODE_ARCH: x64
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
echo "NPMRC Path: $(npm config get userconfig)"
echo "NPM Registry: $(npm config get registry)"
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: sudo apt update -y && sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libnotify-bin libkrb5-dev
displayName: Install build tools
condition: succeeded()
- script: |
set -e
for attempt in {1..6}; do
if [ $attempt -gt 1 ]; then
echo "Attempt $attempt: Waiting for 1 hour before retrying..."
sleep 3600
fi
echo "Attempt $attempt: Running npm ci"
if npm i --ignore-scripts; then
if node build/npm/postinstall.js; then
echo "npm i succeeded on attempt $attempt"
exit 0
else
echo "node build/npm/postinstall.js failed on attempt $attempt"
fi
else
echo "npm i failed on attempt $attempt"
fi
done
echo "npm i failed after 6 attempts"
exit 1
env:
npm_command: 'install --ignore-scripts'
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install dependencies with retries
timeoutInMinutes: 400
- script: .github/workflows/check-clean-git-state.sh
displayName: Check clean git state
================================================
FILE: build/azure-pipelines/product-publish.yml
================================================
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get ESRP Secrets"
inputs:
azureSubscription: vscode-esrp
KeyVaultName: vscode-esrp
SecretsFilter: esrp-auth,esrp-sign
# allow-any-unicode-next-line
- pwsh: Write-Host "##vso[build.addbuildtag]🚀"
displayName: Add build tag
- pwsh: |
npm ci
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install build dependencies
- download: current
patterns: "**/artifacts_processed_*.txt"
displayName: Download all artifacts_processed text files
- task: AzureCLI@2
displayName: Fetch secrets
inputs:
azureSubscription: vscode
scriptType: pscore
scriptLocation: inlineScript
addSpnToEnvironment: true
inlineScript: |
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken"
- pwsh: |
. build/azure-pipelines/win32/exec.ps1
if (Test-Path "$(Pipeline.Workspace)/artifacts_processed_*/artifacts_processed_*.txt") {
Write-Host "Artifacts already processed so a build must have already been created."
return
}
$VERSION = node -p "require('./package.json').version"
Write-Host "Creating build with version: $VERSION"
exec { node build/azure-pipelines/common/createBuild.js $VERSION }
env:
AZURE_TENANT_ID: "$(AZURE_TENANT_ID)"
AZURE_CLIENT_ID: "$(AZURE_CLIENT_ID)"
AZURE_ID_TOKEN: "$(AZURE_ID_TOKEN)"
displayName: Create build if it hasn't been created before
- pwsh: |
$publishAuthTokens = (node build/azure-pipelines/common/getPublishAuthTokens)
Write-Host "##vso[task.setvariable variable=PUBLISH_AUTH_TOKENS;issecret=true]$publishAuthTokens"
env:
AZURE_TENANT_ID: "$(AZURE_TENANT_ID)"
AZURE_CLIENT_ID: "$(AZURE_CLIENT_ID)"
AZURE_ID_TOKEN: "$(AZURE_ID_TOKEN)"
displayName: Get publish auth tokens
- pwsh: node build/azure-pipelines/common/publish.js
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
AZURE_TENANT_ID: "$(AZURE_TENANT_ID)"
AZURE_CLIENT_ID: "$(AZURE_CLIENT_ID)"
AZURE_ID_TOKEN: "$(AZURE_ID_TOKEN)"
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
PUBLISH_AUTH_TOKENS: "$(PUBLISH_AUTH_TOKENS)"
RELEASE_TENANT_ID: "$(ESRP_TENANT_ID)"
RELEASE_CLIENT_ID: "$(ESRP_CLIENT_ID)"
RELEASE_AUTH_CERT: "$(esrp-auth)"
RELEASE_REQUEST_SIGNING_CERT: "$(esrp-sign)"
displayName: Process artifacts
retryCountOnTaskFailure: 3
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Pipeline.Workspace)/artifacts_processed_$(System.StageAttempt)/artifacts_processed_$(System.StageAttempt).txt
artifactName: artifacts_processed_$(System.StageAttempt)
sbomEnabled: false
displayName: Publish the artifacts processed for this stage attempt
condition: always()
- pwsh: |
$ErrorActionPreference = 'Stop'
# Determine which stages we need to watch
$stages = @(
if ($env:VSCODE_BUILD_STAGE_WINDOWS -eq 'True') { 'Windows' }
if ($env:VSCODE_BUILD_STAGE_LINUX -eq 'True') { 'Linux' }
if ($env:VSCODE_BUILD_STAGE_ALPINE -eq 'True') { 'Alpine' }
if ($env:VSCODE_BUILD_STAGE_MACOS -eq 'True') { 'macOS' }
if ($env:VSCODE_BUILD_STAGE_WEB -eq 'True') { 'Web' }
)
Write-Host "Stages to check: $stages"
# Get the timeline and see if it says the other stage completed
$timeline = Invoke-RestMethod "$($env:BUILDS_API_URL)timeline?api-version=6.0" -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
} -MaximumRetryCount 5 -RetryIntervalSec 1
$failedStages = @()
foreach ($stage in $stages) {
$didStageFail = $timeline.records | Where-Object {
$_.name -eq $stage -and $_.type -eq 'stage' -and $_.result -ne 'succeeded' -and $_.result -ne 'succeededWithIssues'
}
if($didStageFail) {
$failedStages += $stage
Write-Host "'$stage' failed!"
Write-Host $didStageFail
} else {
Write-Host "'$stage' did not fail."
}
}
if ($failedStages.Length) {
throw "Failed stages: $($failedStages -join ', '). This stage will now fail so that it is easier to retry failed jobs."
}
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Determine if stage should succeed
================================================
FILE: build/azure-pipelines/product-release.yml
================================================
parameters:
- name: VSCODE_RELEASE
type: boolean
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- task: AzureCLI@2
displayName: Fetch secrets
inputs:
azureSubscription: vscode
scriptType: pscore
scriptLocation: inlineScript
addSpnToEnvironment: true
inlineScript: |
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken"
- script: npm ci
workingDirectory: build
displayName: Install /build dependencies
- script: |
set -e
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \
node build/azure-pipelines/common/releaseBuild.js ${{ parameters.VSCODE_RELEASE }}
displayName: Release build
================================================
FILE: build/azure-pipelines/publish-types/check-version.js
================================================
"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 child_process_1 = __importDefault(require("child_process"));
let tag = '';
try {
tag = child_process_1.default
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
if (!isValidTag(tag)) {
throw Error(`Invalid tag ${tag}`);
}
}
catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function isValidTag(t) {
if (t.split('.').length !== 3) {
return false;
}
const [major, minor, bug] = t.split('.');
// Only release for tags like 1.34.0
if (bug !== '0') {
return false;
}
if (isNaN(parseInt(major, 10)) || isNaN(parseInt(minor, 10))) {
return false;
}
return true;
}
//# sourceMappingURL=check-version.js.map
================================================
FILE: build/azure-pipelines/publish-types/check-version.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import cp from 'child_process';
let tag = '';
try {
tag = cp
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
if (!isValidTag(tag)) {
throw Error(`Invalid tag ${tag}`);
}
} catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function isValidTag(t: string) {
if (t.split('.').length !== 3) {
return false;
}
const [major, minor, bug] = t.split('.');
// Only release for tags like 1.34.0
if (bug !== '0') {
return false;
}
if (isNaN(parseInt(major, 10)) || isNaN(parseInt(minor, 10))) {
return false;
}
return true;
}
================================================
FILE: build/azure-pipelines/publish-types/publish-types.yml
================================================
# Publish @types/vscode for each release
trigger:
branches:
include: ["refs/tags/*"]
pr: none
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- bash: |
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
CHANNEL="C1C14HJ2F"
if [ "$TAG_VERSION" == "1.999.0" ]; then
MESSAGE=". Someone pushed 1.999.0 tag. Please delete it ASAP from remote and local."
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \
https://slack.com/api/chat.postMessage
exit 1
fi
displayName: Check 1.999.0 tag
- bash: |
# Install build dependencies
(cd build && npm ci)
node build/azure-pipelines/publish-types/check-version.js
displayName: Check version
- bash: |
git config --global user.email "vscode@microsoft.com"
git config --global user.name "VSCode"
git clone https://$(GITHUB_TOKEN)@github.com/DefinitelyTyped/DefinitelyTyped.git --depth=1
node build/azure-pipelines/publish-types/update-types.js
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
cd DefinitelyTyped
git diff --color | cat
git add -A
git status
git checkout -b "vscode-types-$TAG_VERSION"
git commit -m "VS Code $TAG_VERSION Extension API"
git push origin "vscode-types-$TAG_VERSION"
displayName: Push update to DefinitelyTyped
- bash: |
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
CHANNEL="C1C14HJ2F"
MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame champion, please open this link, examine changes and create a PR:"
LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details."
MESSAGE2="[@jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode."
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \
https://slack.com/api/chat.postMessage
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$LINK"'"}' \
https://slack.com/api/chat.postMessage
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE2"'"}' \
https://slack.com/api/chat.postMessage
displayName: Send message linking to changes on Slack
================================================
FILE: build/azure-pipelines/publish-types/update-types.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const child_process_1 = __importDefault(require("child_process"));
const path_1 = __importDefault(require("path"));
let tag = '';
try {
tag = child_process_1.default
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vscode-dts/vscode.d.ts`;
const outPath = path_1.default.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts');
child_process_1.default.execSync(`curl ${dtsUri} --output ${outPath}`);
updateDTSFile(outPath, tag);
console.log(`Done updating vscode.d.ts at ${outPath}`);
}
catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function updateDTSFile(outPath, tag) {
const oldContent = fs_1.default.readFileSync(outPath, 'utf-8');
const newContent = getNewFileContent(oldContent, tag);
fs_1.default.writeFileSync(outPath, newContent);
}
function repeat(str, times) {
const result = new Array(times);
for (let i = 0; i < times; i++) {
result[i] = str;
}
return result.join('');
}
function convertTabsToSpaces(str) {
return str.replace(/\t/gm, value => repeat(' ', value.length));
}
function getNewFileContent(content, tag) {
const oldheader = [
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the MIT License. See License.txt in the project root for license information.`,
` *--------------------------------------------------------------------------------------------*/`
].join('\n');
return convertTabsToSpaces(getNewFileHeader(tag) + content.slice(oldheader.length));
}
function getNewFileHeader(tag) {
const [major, minor] = tag.split('.');
const shorttag = `${major}.${minor}`;
const header = [
`// Type definitions for Visual Studio Code ${shorttag}`,
`// Project: https://github.com/microsoft/vscode`,
`// Definitions by: Visual Studio Code Team, Microsoft `,
`// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped`,
``,
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the MIT License.`,
` * See https://github.com/microsoft/vscode/blob/main/LICENSE.txt for license information.`,
` *--------------------------------------------------------------------------------------------*/`,
``,
`/**`,
` * Type Definition for Visual Studio Code ${shorttag} Extension API`,
` * See https://code.visualstudio.com/api for more information`,
` */`
].join('\n');
return header;
}
//# sourceMappingURL=update-types.js.map
================================================
FILE: build/azure-pipelines/publish-types/update-types.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import cp from 'child_process';
import path from 'path';
let tag = '';
try {
tag = cp
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vscode-dts/vscode.d.ts`;
const outPath = path.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts');
cp.execSync(`curl ${dtsUri} --output ${outPath}`);
updateDTSFile(outPath, tag);
console.log(`Done updating vscode.d.ts at ${outPath}`);
} catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function updateDTSFile(outPath: string, tag: string) {
const oldContent = fs.readFileSync(outPath, 'utf-8');
const newContent = getNewFileContent(oldContent, tag);
fs.writeFileSync(outPath, newContent);
}
function repeat(str: string, times: number): string {
const result = new Array(times);
for (let i = 0; i < times; i++) {
result[i] = str;
}
return result.join('');
}
function convertTabsToSpaces(str: string): string {
return str.replace(/\t/gm, value => repeat(' ', value.length));
}
function getNewFileContent(content: string, tag: string) {
const oldheader = [
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the MIT License. See License.txt in the project root for license information.`,
` *--------------------------------------------------------------------------------------------*/`
].join('\n');
return convertTabsToSpaces(getNewFileHeader(tag) + content.slice(oldheader.length));
}
function getNewFileHeader(tag: string) {
const [major, minor] = tag.split('.');
const shorttag = `${major}.${minor}`;
const header = [
`// Type definitions for Visual Studio Code ${shorttag}`,
`// Project: https://github.com/microsoft/vscode`,
`// Definitions by: Visual Studio Code Team, Microsoft `,
`// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped`,
``,
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the MIT License.`,
` * See https://github.com/microsoft/vscode/blob/main/LICENSE.txt for license information.`,
` *--------------------------------------------------------------------------------------------*/`,
``,
`/**`,
` * Type Definition for Visual Studio Code ${shorttag} Extension API`,
` * See https://code.visualstudio.com/api for more information`,
` */`
].join('\n');
return header;
}
================================================
FILE: build/azure-pipelines/upload-cdn.js
================================================
"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 event_stream_1 = __importDefault(require("event-stream"));
const vinyl_1 = __importDefault(require("vinyl"));
const vinyl_fs_1 = __importDefault(require("vinyl-fs"));
const gulp_filter_1 = __importDefault(require("gulp-filter"));
const gulp_gzip_1 = __importDefault(require("gulp-gzip"));
const mime_1 = __importDefault(require("mime"));
const identity_1 = require("@azure/identity");
const azure = 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({
'application/typescript': ['ts'],
'application/json': ['code-snippets'],
});
// From default AFD configuration
const MimeTypesToCompress = new Set([
'application/eot',
'application/font',
'application/font-sfnt',
'application/javascript',
'application/json',
'application/opentype',
'application/otf',
'application/pkcs7-mime',
'application/truetype',
'application/ttf',
'application/typescript',
'application/vnd.ms-fontobject',
'application/xhtml+xml',
'application/xml',
'application/xml+rss',
'application/x-font-opentype',
'application/x-font-truetype',
'application/x-font-ttf',
'application/x-httpd-cgi',
'application/x-javascript',
'application/x-mpegurl',
'application/x-opentype',
'application/x-otf',
'application/x-perl',
'application/x-ttf',
'font/eot',
'font/ttf',
'font/otf',
'font/opentype',
'image/svg+xml',
'text/css',
'text/csv',
'text/html',
'text/javascript',
'text/js',
'text/markdown',
'text/plain',
'text/richtext',
'text/tab-separated-values',
'text/xml',
'text/x-script',
'text/x-component',
'text/x-java-source'
]);
function wait(stream) {
return new Promise((c, e) => {
stream.on('end', () => c());
stream.on('error', (err) => e(err));
});
}
async function main() {
const files = [];
const options = (compressed) => ({
account: process.env.AZURE_STORAGE_ACCOUNT,
credential,
container: '$web',
prefix: `${process.env.VSCODE_QUALITY}/${commit}/`,
contentSettings: {
contentEncoding: compressed ? 'gzip' : undefined,
cacheControl: 'max-age=31536000, public'
}
});
const all = vinyl_fs_1.default.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true })
.pipe((0, gulp_filter_1.default)(f => !f.isDirectory()));
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)));
const uncompressed = all
.pipe((0, gulp_filter_1.default)(f => !MimeTypesToCompress.has(mime_1.default.lookup(f.path))))
.pipe(azure.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);
files.push(f.relative);
this.emit('data', f);
}));
console.log(`Uploading files to CDN...`); // debug
await wait(out);
const listing = new vinyl_1.default({
path: 'files.txt',
contents: Buffer.from(files.join('\n')),
stat: { mode: 0o666 }
});
const filesOut = event_stream_1.default.readArray([listing])
.pipe((0, gulp_gzip_1.default)({ append: false }))
.pipe(azure.upload(options(true)));
console.log(`Uploading: files.txt (${files.length} files)`); // debug
await wait(filesOut);
}
main().catch(err => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=upload-cdn.js.map
================================================
FILE: build/azure-pipelines/upload-cdn.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import es from 'event-stream';
import Vinyl from 'vinyl';
import vfs from 'vinyl-fs';
import filter from 'gulp-filter';
import gzip from 'gulp-gzip';
import mime from 'mime';
import { ClientAssertionCredential } from '@azure/identity';
const azure = require('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']!));
mime.define({
'application/typescript': ['ts'],
'application/json': ['code-snippets'],
});
// From default AFD configuration
const MimeTypesToCompress = new Set([
'application/eot',
'application/font',
'application/font-sfnt',
'application/javascript',
'application/json',
'application/opentype',
'application/otf',
'application/pkcs7-mime',
'application/truetype',
'application/ttf',
'application/typescript',
'application/vnd.ms-fontobject',
'application/xhtml+xml',
'application/xml',
'application/xml+rss',
'application/x-font-opentype',
'application/x-font-truetype',
'application/x-font-ttf',
'application/x-httpd-cgi',
'application/x-javascript',
'application/x-mpegurl',
'application/x-opentype',
'application/x-otf',
'application/x-perl',
'application/x-ttf',
'font/eot',
'font/ttf',
'font/otf',
'font/opentype',
'image/svg+xml',
'text/css',
'text/csv',
'text/html',
'text/javascript',
'text/js',
'text/markdown',
'text/plain',
'text/richtext',
'text/tab-separated-values',
'text/xml',
'text/x-script',
'text/x-component',
'text/x-java-source'
]);
function wait(stream: es.ThroughStream): Promise {
return new Promise((c, e) => {
stream.on('end', () => c());
stream.on('error', (err: any) => e(err));
});
}
async function main(): Promise {
const files: string[] = [];
const options = (compressed: boolean) => ({
account: process.env.AZURE_STORAGE_ACCOUNT,
credential,
container: '$web',
prefix: `${process.env.VSCODE_QUALITY}/${commit}/`,
contentSettings: {
contentEncoding: compressed ? 'gzip' : undefined,
cacheControl: 'max-age=31536000, public'
}
});
const all = vfs.src('**', { cwd: '../vscode-web', base: '../vscode-web', dot: true })
.pipe(filter(f => !f.isDirectory()));
const compressed = all
.pipe(filter(f => MimeTypesToCompress.has(mime.lookup(f.path))))
.pipe(gzip({ append: false }))
.pipe(azure.upload(options(true)));
const uncompressed = all
.pipe(filter(f => !MimeTypesToCompress.has(mime.lookup(f.path))))
.pipe(azure.upload(options(false)));
const out = es.merge(compressed, uncompressed)
.pipe(es.through(function (f) {
console.log('Uploaded:', f.relative);
files.push(f.relative);
this.emit('data', f);
}));
console.log(`Uploading files to CDN...`); // debug
await wait(out);
const listing = new Vinyl({
path: 'files.txt',
contents: Buffer.from(files.join('\n')),
stat: { mode: 0o666 } as any
});
const filesOut = es.readArray([listing])
.pipe(gzip({ append: false }))
.pipe(azure.upload(options(true)));
console.log(`Uploading: files.txt (${files.length} files)`); // debug
await wait(filesOut);
}
main().catch(err => {
console.error(err);
process.exit(1);
});
================================================
FILE: build/azure-pipelines/upload-nlsmetadata.js
================================================
"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 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"));
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 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() {
return new Promise((c, e) => {
const combinedMetadataJson = event_stream_1.default.merge(
// vscode: we are not using `out-build/nls.metadata.json` here because
// it includes metadata for translators for `keys`. but for our purpose
// we want only the `keys` and `messages` as `string`.
event_stream_1.default.merge(vinyl_fs_1.default.src('out-build/nls.keys.json', { base: 'out-build' }), vinyl_fs_1.default.src('out-build/nls.messages.json', { base: 'out-build' }))
.pipe((0, gulp_merge_json_1.default)({
fileName: 'vscode.json',
jsonSpace: '',
concatArrays: true,
edit: (parsedJson, file) => {
if (file.base === 'out-build') {
if (file.basename === 'nls.keys.json') {
return { keys: parsedJson };
}
else {
return { messages: parsedJson };
}
}
}
})),
// extensions
vinyl_fs_1.default.src('.build/extensions/**/nls.metadata.json', { base: '.build/extensions' }), vinyl_fs_1.default.src('.build/extensions/**/nls.metadata.header.json', { base: '.build/extensions' }), vinyl_fs_1.default.src('.build/extensions/**/package.nls.json', { base: '.build/extensions' })).pipe((0, gulp_merge_json_1.default)({
fileName: 'combined.nls.metadata.json',
jsonSpace: '',
concatArrays: true,
edit: (parsedJson, file) => {
if (file.basename === 'vscode.json') {
return { vscode: parsedJson };
}
// Handle extensions and follow the same structure as the Core nls file.
switch (file.basename) {
case 'package.nls.json':
// put package.nls.json content in Core NlsMetadata format
// language packs use the key "package" to specify that
// translations are for the package.json file
parsedJson = {
messages: {
package: Object.values(parsedJson)
},
keys: {
package: Object.keys(parsedJson)
},
bundles: {
main: ['package']
}
};
break;
case 'nls.metadata.header.json':
parsedJson = { header: parsedJson };
break;
case 'nls.metadata.json': {
// put nls.metadata.json content in Core NlsMetadata format
const modules = Object.keys(parsedJson);
const json = {
keys: {},
messages: {},
bundles: {
main: []
}
};
for (const module of modules) {
json.messages[module] = parsedJson[module].messages;
json.keys[module] = parsedJson[module].keys;
json.bundles.main.push(module);
}
parsedJson = json;
break;
}
}
// Get extension id and use that as the key
const folderPath = path.join(file.base, file.relative.split('/')[0]);
const manifest = (0, fs_1.readFileSync)(path.join(folderPath, 'package.json'), 'utf-8');
const manifestJson = JSON.parse(manifest);
const key = manifestJson.publisher + '.' + manifestJson.name;
return { [key]: parsedJson };
},
}));
const nlsMessagesJs = vinyl_fs_1.default.src('out-build/nls.messages.js', { base: 'out-build' });
event_stream_1.default.merge(combinedMetadataJson, nlsMessagesJs)
.pipe((0, gulp_gzip_1.default)({ append: false }))
.pipe(vinyl_fs_1.default.dest('./nlsMetadata'))
.pipe(event_stream_1.default.through(function (data) {
console.log(`Uploading ${data.path}`);
// trigger artifact upload
console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=${data.basename}]${data.path}`);
this.emit('data', data);
}))
.pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT,
credential,
container: '$web',
prefix: `nlsmetadata/${commit}/`,
contentSettings: {
contentEncoding: 'gzip',
cacheControl: 'max-age=31536000, public'
}
}))
.on('end', () => c())
.on('error', (err) => e(err));
});
}
main().catch(err => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=upload-nlsmetadata.js.map
================================================
FILE: build/azure-pipelines/upload-nlsmetadata.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import es from 'event-stream';
import Vinyl from 'vinyl';
import vfs from 'vinyl-fs';
import merge from 'gulp-merge-json';
import gzip from 'gulp-gzip';
import { ClientAssertionCredential } from '@azure/identity';
import path = require('path');
import { readFileSync } from 'fs';
const azure = require('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']!));
interface NlsMetadata {
keys: { [module: string]: string };
messages: { [module: string]: string };
bundles: { [bundle: string]: string[] };
}
function main(): Promise {
return new Promise((c, e) => {
const combinedMetadataJson = es.merge(
// vscode: we are not using `out-build/nls.metadata.json` here because
// it includes metadata for translators for `keys`. but for our purpose
// we want only the `keys` and `messages` as `string`.
es.merge(
vfs.src('out-build/nls.keys.json', { base: 'out-build' }),
vfs.src('out-build/nls.messages.json', { base: 'out-build' }))
.pipe(merge({
fileName: 'vscode.json',
jsonSpace: '',
concatArrays: true,
edit: (parsedJson, file) => {
if (file.base === 'out-build') {
if (file.basename === 'nls.keys.json') {
return { keys: parsedJson };
} else {
return { messages: parsedJson };
}
}
}
})),
// extensions
vfs.src('.build/extensions/**/nls.metadata.json', { base: '.build/extensions' }),
vfs.src('.build/extensions/**/nls.metadata.header.json', { base: '.build/extensions' }),
vfs.src('.build/extensions/**/package.nls.json', { base: '.build/extensions' })
).pipe(merge({
fileName: 'combined.nls.metadata.json',
jsonSpace: '',
concatArrays: true,
edit: (parsedJson, file) => {
if (file.basename === 'vscode.json') {
return { vscode: parsedJson };
}
// Handle extensions and follow the same structure as the Core nls file.
switch (file.basename) {
case 'package.nls.json':
// put package.nls.json content in Core NlsMetadata format
// language packs use the key "package" to specify that
// translations are for the package.json file
parsedJson = {
messages: {
package: Object.values(parsedJson)
},
keys: {
package: Object.keys(parsedJson)
},
bundles: {
main: ['package']
}
};
break;
case 'nls.metadata.header.json':
parsedJson = { header: parsedJson };
break;
case 'nls.metadata.json': {
// put nls.metadata.json content in Core NlsMetadata format
const modules = Object.keys(parsedJson);
const json: NlsMetadata = {
keys: {},
messages: {},
bundles: {
main: []
}
};
for (const module of modules) {
json.messages[module] = parsedJson[module].messages;
json.keys[module] = parsedJson[module].keys;
json.bundles.main.push(module);
}
parsedJson = json;
break;
}
}
// Get extension id and use that as the key
const folderPath = path.join(file.base, file.relative.split('/')[0]);
const manifest = readFileSync(path.join(folderPath, 'package.json'), 'utf-8');
const manifestJson = JSON.parse(manifest);
const key = manifestJson.publisher + '.' + manifestJson.name;
return { [key]: parsedJson };
},
}));
const nlsMessagesJs = vfs.src('out-build/nls.messages.js', { base: 'out-build' });
es.merge(combinedMetadataJson, nlsMessagesJs)
.pipe(gzip({ append: false }))
.pipe(vfs.dest('./nlsMetadata'))
.pipe(es.through(function (data: Vinyl) {
console.log(`Uploading ${data.path}`);
// trigger artifact upload
console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=${data.basename}]${data.path}`);
this.emit('data', data);
}))
.pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT,
credential,
container: '$web',
prefix: `nlsmetadata/${commit}/`,
contentSettings: {
contentEncoding: 'gzip',
cacheControl: 'max-age=31536000, public'
}
}))
.on('end', () => c())
.on('error', (err: any) => e(err));
});
}
main().catch(err => {
console.error(err);
process.exit(1);
});
================================================
FILE: build/azure-pipelines/upload-sourcemaps.js
================================================
"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 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 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']));
// optionally allow to pass in explicit base/maps to upload
const [, , base, maps] = process.argv;
function src(base, maps = `${base}/**/*.map`) {
return vinyl_fs_1.default.src(maps, { base })
.pipe(event_stream_1.default.mapSync((f) => {
f.path = `${f.base}/core/${f.relative}`;
return f;
}));
}
function main() {
const sources = [];
// vscode client maps (default)
if (!base) {
const vs = src('out-vscode-min'); // client source-maps only
sources.push(vs);
const productionDependencies = (0, dependencies_1.getProductionDependencies)(root);
const productionDependenciesSrc = productionDependencies.map((d) => path_1.default.relative(root, d)).map((d) => `./${d}/**/*.map`);
const nodeModules = vinyl_fs_1.default.src(productionDependenciesSrc, { base: '.' })
.pipe(util.cleanNodeModules(path_1.default.join(root, 'build', '.moduleignore')))
.pipe(util.cleanNodeModules(path_1.default.join(root, 'build', `.moduleignore.${process.platform}`)));
sources.push(nodeModules);
const extensionsOut = vinyl_fs_1.default.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' });
sources.push(extensionsOut);
}
// specific client base/maps
else {
sources.push(src(base, maps));
}
return new Promise((c, e) => {
event_stream_1.default.merge(...sources)
.pipe(event_stream_1.default.through(function (data) {
console.log('Uploading Sourcemap', data.relative); // debug
this.emit('data', data);
}))
.pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT,
credential,
container: '$web',
prefix: `sourcemaps/${commit}/`
}))
.on('end', () => c())
.on('error', (err) => e(err));
});
}
main().catch(err => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=upload-sourcemaps.js.map
================================================
FILE: build/azure-pipelines/upload-sourcemaps.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import path from 'path';
import es from 'event-stream';
import Vinyl from 'vinyl';
import vfs from 'vinyl-fs';
import * as util from '../lib/util';
import { getProductionDependencies } from '../lib/dependencies';
import { ClientAssertionCredential } from '@azure/identity';
const azure = require('gulp-azure-storage');
const root = path.dirname(path.dirname(__dirname));
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']!));
// optionally allow to pass in explicit base/maps to upload
const [, , base, maps] = process.argv;
function src(base: string, maps = `${base}/**/*.map`) {
return vfs.src(maps, { base })
.pipe(es.mapSync((f: Vinyl) => {
f.path = `${f.base}/core/${f.relative}`;
return f;
}));
}
function main(): Promise {
const sources: any[] = [];
// vscode client maps (default)
if (!base) {
const vs = src('out-vscode-min'); // client source-maps only
sources.push(vs);
const productionDependencies = getProductionDependencies(root);
const productionDependenciesSrc = productionDependencies.map((d: string) => path.relative(root, d)).map((d: string) => `./${d}/**/*.map`);
const nodeModules = vfs.src(productionDependenciesSrc, { base: '.' })
.pipe(util.cleanNodeModules(path.join(root, 'build', '.moduleignore')))
.pipe(util.cleanNodeModules(path.join(root, 'build', `.moduleignore.${process.platform}`)));
sources.push(nodeModules);
const extensionsOut = vfs.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' });
sources.push(extensionsOut);
}
// specific client base/maps
else {
sources.push(src(base, maps));
}
return new Promise((c, e) => {
es.merge(...sources)
.pipe(es.through(function (data: Vinyl) {
console.log('Uploading Sourcemap', data.relative); // debug
this.emit('data', data);
}))
.pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT,
credential,
container: '$web',
prefix: `sourcemaps/${commit}/`
}))
.on('end', () => c())
.on('error', (err: any) => e(err));
});
}
main().catch(err => {
console.error(err);
process.exit(1);
});
================================================
FILE: build/azure-pipelines/web/product-build-web.yml
================================================
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- task: DownloadPipelineArtifact@2
inputs:
artifact: Compilation
path: $(Build.ArtifactStagingDirectory)
displayName: Download compilation output
- script: tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
displayName: Extract compilation output
- script: node build/setup-npm-registry.js $NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js web > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- script: tar -xzf .build/node_modules_cache/cache.tgz
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- script: |
set -e
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
npm config set registry "$NPM_REGISTRY"
echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- script: |
set -e
./build/azure-pipelines/linux/apt-retry.sh sudo apt-get update
./build/azure-pipelines/linux/apt-retry.sh sudo apt-get install -y libkrb5-dev
displayName: Setup system services
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: |
set -e
for i in {1..5}; do # try 5 times
npm ci && break
if [ $i -eq 5 ]; then
echo "Npm install failed too many times" >&2
exit 1
fi
echo "Npm install failed $i, trying again..."
done
env:
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- script: node build/azure-pipelines/distro/mixin-npm
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Mixin distro node modules
- script: |
set -e
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
mkdir -p .build/node_modules_cache
tar -czf .build/node_modules_cache/cache.tgz --files-from .build/node_modules_list.txt
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- template: ../common/install-builtin-extensions.yml@self
- script: |
set -e
npm run gulp vscode-web-min-ci
ARCHIVE_PATH=".build/web/vscode-web.tar.gz"
mkdir -p $(dirname $ARCHIVE_PATH)
tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-web
echo "##vso[task.setvariable variable=WEB_PATH]$ARCHIVE_PATH"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build
- task: AzureCLI@2
displayName: Fetch secrets from Azure
inputs:
azureSubscription: vscode
scriptType: pscore
scriptLocation: inlineScript
addSpnToEnvironment: true
inlineScript: |
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken"
- script: |
set -e
AZURE_STORAGE_ACCOUNT="vscodeweb" \
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \
node build/azure-pipelines/upload-cdn
displayName: Upload to CDN
- script: |
set -e
AZURE_STORAGE_ACCOUNT="vscodeweb" \
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \
node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.js.map
displayName: Upload sourcemaps (Web Main)
- script: |
set -e
AZURE_STORAGE_ACCOUNT="vscodeweb" \
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \
node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.internal.js.map
displayName: Upload sourcemaps (Web Internal)
- script: |
set -e
AZURE_STORAGE_ACCOUNT="vscodeweb" \
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \
node build/azure-pipelines/upload-nlsmetadata
displayName: Upload NLS Metadata
- script: echo "##vso[task.setvariable variable=ARTIFACT_PREFIX]attempt$(System.JobAttempt)_"
condition: and(succeededOrFailed(), notIn(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues'))
displayName: Generate artifact prefix
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(WEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_web_linux_standalone_archive-unsigned
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-web
sbomPackageName: "VS Code Web"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], ''))
displayName: Publish web archive
================================================
FILE: build/azure-pipelines/win32/cli-build-win32.yml
================================================
parameters:
- name: VSCODE_BUILD_WIN32
type: boolean
default: false
- name: VSCODE_BUILD_WIN32_ARM64
type: boolean
default: false
- name: VSCODE_CHECK_ONLY
type: boolean
default: false
- name: VSCODE_QUALITY
type: string
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../cli/cli-apply-patches.yml@self
- task: Npm@1
displayName: Download openssl prebuilt
inputs:
command: custom
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.11
customRegistry: useFeed
customFeed: "Monaco/openssl-prebuilt"
workingDir: $(Build.ArtifactStagingDirectory)
- powershell: |
mkdir $(Build.ArtifactStagingDirectory)/openssl
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.11.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
displayName: Extract openssl prebuilt
- template: ../cli/install-rust-win32.yml@self
parameters:
targets:
- ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
- x86_64-pc-windows-msvc
- ${{ if eq(parameters.VSCODE_BUILD_WIN32_ARM64, true) }}:
- aarch64-pc-windows-msvc
- ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: x86_64-pc-windows-msvc
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_win32_x64_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-windows-static/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-windows-static/include
RUSTFLAGS: "-Ctarget-feature=+crt-static -Clink-args=/guard:cf -Clink-args=/CETCOMPAT"
CFLAGS: "/guard:cf /Qspectre"
- ${{ if eq(parameters.VSCODE_BUILD_WIN32_ARM64, true) }}:
- template: ../cli/cli-compile.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_CLI_TARGET: aarch64-pc-windows-msvc
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_win32_arm64_cli
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
VSCODE_CLI_ENV:
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-windows-static/lib
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-windows-static/include
RUSTFLAGS: "-C target-feature=+crt-static -Clink-args=/guard:cf -Clink-args=/CETCOMPAT:NO"
CFLAGS: "/guard:cf /Qspectre"
- ${{ if not(parameters.VSCODE_CHECK_ONLY) }}:
- ${{ if eq(parameters.VSCODE_BUILD_WIN32_ARM64, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/unsigned_vscode_cli_win32_arm64_cli.zip
artifactName: unsigned_vscode_cli_win32_arm64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Windows arm64 CLI (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish unsigned_vscode_cli_win32_arm64_cli artifact
- ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)/unsigned_vscode_cli_win32_x64_cli.zip
artifactName: unsigned_vscode_cli_win32_x64_cli
sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/cli
sbomPackageName: "VS Code Windows x64 CLI (unsigned)"
sbomPackageVersion: $(Build.SourceVersion)
displayName: Publish unsigned_vscode_cli_win32_x64_cli artifact
================================================
FILE: build/azure-pipelines/win32/exec.ps1
================================================
# Taken from psake https://github.com/psake/psake
<#
.SYNOPSIS
This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode
to see if an error occcured. If an error is detected then an exception is thrown.
This function allows you to run command-line programs without having to
explicitly check the $lastexitcode variable.
.EXAMPLE
exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed"
#>
function Exec
{
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,
[Parameter(Position=1,Mandatory=0)][string]$errorMessage = ($msgs.error_bad_command -f $cmd)
)
& $cmd
if ($lastexitcode -ne 0) {
throw ("Exec: " + $errorMessage)
}
}
================================================
FILE: build/azure-pipelines/win32/import-esrp-auth-cert.ps1
================================================
param ($CertBase64)
$ErrorActionPreference = "Stop"
$CertBytes = [System.Convert]::FromBase64String($CertBase64)
$CertCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$CertCollection.Import($CertBytes, $null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable -bxor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)
$CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine")
$CertStore.Open("ReadWrite")
$CertStore.AddRange($CertCollection)
$CertStore.Close()
$ESRPAuthCertificateSubjectName = $CertCollection[0].Subject
Write-Output ("##vso[task.setvariable variable=ESRPAuthCertificateSubjectName;]$ESRPAuthCertificateSubjectName")
================================================
FILE: build/azure-pipelines/win32/listprocesses.bat
================================================
echo "------------------------------------"
tasklist /V
echo "------------------------------------"
================================================
FILE: build/azure-pipelines/win32/product-build-win32-cli-sign.yml
================================================
parameters:
- name: VSCODE_BUILD_WIN32
type: boolean
- name: VSCODE_BUILD_WIN32_ARM64
type: boolean
- name: VSCODE_QUALITY
type: string
steps:
- task: NodeTool@0
displayName: "Use Node.js"
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- powershell: node build/setup-npm-registry.js $env:NPM_REGISTRY build
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
exec { npm config set registry "$env:NPM_REGISTRY" }
$NpmrcPath = (npm config get userconfig)
echo "##vso[task.setvariable variable=NPMRC_PATH]$NpmrcPath"
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- powershell: |
. azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm ci }
workingDirectory: build
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
retryCountOnTaskFailure: 5
displayName: Install build dependencies
- template: ../cli/cli-win32-sign.yml@self
parameters:
VSCODE_CLI_ARTIFACTS:
- ${{ if eq(parameters.VSCODE_BUILD_WIN32, true) }}:
- unsigned_vscode_cli_win32_x64_cli
- ${{ if eq(parameters.VSCODE_BUILD_WIN32_ARM64, true) }}:
- unsigned_vscode_cli_win32_arm64_cli
================================================
FILE: build/azure-pipelines/win32/product-build-win32-test.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_ARCH
type: string
- name: VSCODE_RUN_UNIT_TESTS
type: boolean
- name: VSCODE_RUN_INTEGRATION_TESTS
type: boolean
- name: VSCODE_RUN_SMOKE_TESTS
type: boolean
- name: PUBLISH_TASK_NAME
type: string
default: PublishPipelineArtifact@0
steps:
- powershell: npm exec -- npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Download Electron and Playwright
retryCountOnTaskFailure: 3
- ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: .\scripts\test.bat --tfs "Unit Tests"
displayName: Run unit tests (Electron)
timeoutInMinutes: 15
- powershell: npm run test-node
displayName: Run unit tests (node.js)
timeoutInMinutes: 15
- powershell: node test/unit/browser/index.js --browser chromium --tfs "Browser Unit Tests"
displayName: Run unit tests (Browser, Chromium)
timeoutInMinutes: 20
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: .\scripts\test.bat --build --tfs "Unit Tests"
displayName: Run unit tests (Electron)
timeoutInMinutes: 15
- powershell: npm run test-node -- --build
displayName: Run unit tests (node.js)
timeoutInMinutes: 15
- powershell: npm run test-browser-no-install -- --build --browser chromium --tfs "Browser Unit Tests"
displayName: Run unit tests (Browser, Chromium)
timeoutInMinutes: 20
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp `
compile-extension:configuration-editing `
compile-extension:css-language-features-server `
compile-extension:emmet `
compile-extension:git `
compile-extension:github-authentication `
compile-extension:html-language-features-server `
compile-extension:ipynb `
compile-extension:notebook-renderers `
compile-extension:json-language-features-server `
compile-extension:markdown-language-features `
compile-extension-media `
compile-extension:microsoft-authentication `
compile-extension:typescript-language-features `
compile-extension:vscode-api-tests `
compile-extension:vscode-colorize-tests `
compile-extension:vscode-colorize-perf-tests `
compile-extension:vscode-test-resolver `
}
displayName: Build integration tests
- powershell: .\build\azure-pipelines\win32\listprocesses.bat
displayName: Diagnostics before integration test runs
continueOnError: true
condition: succeededOrFailed()
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: .\scripts\test-integration.bat --tfs "Integration Tests"
displayName: Run integration tests (Electron)
timeoutInMinutes: 20
- powershell: .\scripts\test-web-integration.bat --browser chromium
displayName: Run integration tests (Browser, Chromium)
timeoutInMinutes: 20
- powershell: .\scripts\test-remote-integration.bat
displayName: Run integration tests (Remote)
timeoutInMinutes: 20
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: |
# Figure out the full absolute path of the product we just built
# including the remote server and configure the integration tests
# to run with these builds instead of running out of sources.
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
$AppProductJson = Get-Content -Raw -Path "$AppRoot\resources\app\product.json" | ConvertFrom-Json
$AppNameShort = $AppProductJson.nameShort
$env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-server-win32-$(VSCODE_ARCH)"
exec { .\scripts\test-integration.bat --build --tfs "Integration Tests" }
displayName: Run integration tests (Electron)
timeoutInMinutes: 20
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-server-win32-$(VSCODE_ARCH)-web"
exec { .\scripts\test-web-integration.bat --browser firefox }
displayName: Run integration tests (Browser, Firefox)
timeoutInMinutes: 20
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
$AppProductJson = Get-Content -Raw -Path "$AppRoot\resources\app\product.json" | ConvertFrom-Json
$AppNameShort = $AppProductJson.nameShort
$env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-server-win32-$(VSCODE_ARCH)"
exec { .\scripts\test-remote-integration.bat }
displayName: Run integration tests (Remote)
timeoutInMinutes: 20
- powershell: .\build\azure-pipelines\win32\listprocesses.bat
displayName: Diagnostics after integration test runs
continueOnError: true
condition: succeededOrFailed()
- ${{ if eq(parameters.VSCODE_RUN_SMOKE_TESTS, true) }}:
- powershell: .\build\azure-pipelines\win32\listprocesses.bat
displayName: Diagnostics before smoke test run
continueOnError: true
condition: succeededOrFailed()
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: npm run compile
workingDirectory: test/smoke
displayName: Compile smoke tests
- powershell: npm run gulp compile-extension-media
displayName: Build extensions for smoke tests
- powershell: npm run smoketest-no-compile -- --tracing
displayName: Run smoke tests (Electron)
timeoutInMinutes: 20
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: npm run smoketest-no-compile -- --tracing --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
displayName: Run smoke tests (Electron)
timeoutInMinutes: 20
- powershell: npm run smoketest-no-compile -- --web --tracing --headless
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)\vscode-server-win32-$(VSCODE_ARCH)-web
displayName: Run smoke tests (Browser, Chromium)
timeoutInMinutes: 20
- powershell: npm run gulp compile-extension:vscode-test-resolver
displayName: Compile test resolver extension
timeoutInMinutes: 20
- powershell: npm run smoketest-no-compile -- --tracing --remote --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
env:
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)\vscode-server-win32-$(VSCODE_ARCH)
displayName: Run smoke tests (Remote)
timeoutInMinutes: 20
- powershell: .\build\azure-pipelines\win32\listprocesses.bat
displayName: Diagnostics after smoke test run
continueOnError: true
condition: succeededOrFailed()
- ${{ if or(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
- task: ${{ parameters.PUBLISH_TASK_NAME }}
inputs:
targetPath: .build\crashes
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: crash-dump-windows-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: crash-dump-windows-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: crash-dump-windows-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Crash Reports"
continueOnError: true
condition: failed()
# In order to properly symbolify above crash reports
# (if any), we need the compiled native modules too
- task: ${{ parameters.PUBLISH_TASK_NAME }}
inputs:
targetPath: node_modules
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: node-modules-windows-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: node-modules-windows-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: node-modules-windows-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Node Modules"
continueOnError: true
condition: failed()
- task: ${{ parameters.PUBLISH_TASK_NAME }}
inputs:
targetPath: .build\logs
${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
artifactName: logs-windows-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
artifactName: logs-windows-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
${{ else }}:
artifactName: logs-windows-$(VSCODE_ARCH)-$(System.JobAttempt)
sbomEnabled: false
displayName: "Publish Log Files"
continueOnError: true
condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
testResultsFiles: "*-results.xml"
searchFolder: "$(Build.ArtifactStagingDirectory)/test-results"
condition: succeededOrFailed()
================================================
FILE: build/azure-pipelines/win32/product-build-win32.yml
================================================
parameters:
- name: VSCODE_QUALITY
type: string
- name: VSCODE_ARCH
type: string
- name: VSCODE_CIBUILD
type: boolean
- name: VSCODE_RUN_UNIT_TESTS
type: boolean
- name: VSCODE_RUN_INTEGRATION_TESTS
type: boolean
- name: VSCODE_RUN_SMOKE_TESTS
type: boolean
steps:
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- checkout: self
fetchDepth: 1
retryCountOnTaskFailure: 3
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- task: UsePythonVersion@0
inputs:
versionSpec: "3.x"
addToPath: true
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- task: DownloadPipelineArtifact@2
inputs:
artifact: Compilation
path: $(Build.ArtifactStagingDirectory)
displayName: Download compilation output
- task: ExtractFiles@1
displayName: Extract compilation output
inputs:
archiveFilePatterns: "$(Build.ArtifactStagingDirectory)/compilation.tar.gz"
cleanDestinationFolder: false
- powershell: node build/setup-npm-registry.js $env:NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- pwsh: |
mkdir .build -ea 0
node build/azure-pipelines/common/computeNodeModulesCacheKey.js win32 $(VSCODE_ARCH) > .build/packagelockhash
displayName: Prepare node_modules cache key
- task: Cache@2
inputs:
key: '"node_modules" | .build/packagelockhash'
path: .build/node_modules_cache
cacheHitVar: NODE_MODULES_RESTORED
displayName: Restore node_modules cache
- powershell: 7z.exe x .build/node_modules_cache/cache.7z -aoa
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Extract node_modules cache
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
exec { npm config set registry "$env:NPM_REGISTRY" }
$NpmrcPath = (npm config get userconfig)
echo "##vso[task.setvariable variable=NPMRC_PATH]$NpmrcPath"
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm ci }
env:
npm_config_arch: $(VSCODE_ARCH)
npm_config_foreground_scripts: "true"
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
retryCountOnTaskFailure: 5
displayName: Install dependencies
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: node build/azure-pipelines/distro/mixin-npm
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Mixin distro node modules
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt }
exec { mkdir -Force .build/node_modules_cache }
exec { 7z.exe a .build/node_modules_cache/cache.7z -mx3 `@.build/node_modules_list.txt }
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
displayName: Create node_modules archive
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
- template: ../common/install-builtin-extensions.yml@self
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'oss')) }}:
- powershell: node build\lib\policies win32
displayName: Generate Group Policy definitions
retryCountOnTaskFailure: 3
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: npm run gulp "transpile-client-esbuild" "transpile-extensions"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Transpile client and extensions
- ${{ else }}:
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), eq(parameters.VSCODE_QUALITY, 'insider')) }}:
- powershell: node build/win32/explorer-appx-fetcher .build/win32/appx
displayName: Download Explorer Sparse Package
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp "vscode-win32-$(VSCODE_ARCH)-min-ci" }
exec { npm run gulp "vscode-win32-$(VSCODE_ARCH)-inno-updater" }
echo "##vso[task.setvariable variable=BUILT_CLIENT]true"
echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build client
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp "vscode-reh-win32-$(VSCODE_ARCH)-min-ci" }
mv ..\vscode-reh-win32-$(VSCODE_ARCH) ..\vscode-server-win32-$(VSCODE_ARCH) # TODO@joaomoreno
echo "##vso[task.setvariable variable=BUILT_SERVER]true"
echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(CodeSigningFolderPath),$(Agent.BuildDirectory)/vscode-server-win32-$(VSCODE_ARCH)"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp "vscode-reh-web-win32-$(VSCODE_ARCH)-min-ci" }
mv ..\vscode-reh-web-win32-$(VSCODE_ARCH) ..\vscode-server-win32-$(VSCODE_ARCH)-web # TODO@joaomoreno
echo "##vso[task.setvariable variable=BUILT_WEB]true"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Build server (web)
- ${{ if or(eq(parameters.VSCODE_RUN_UNIT_TESTS, true), eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
- template: product-build-win32-test.yml@self
parameters:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
VSCODE_ARCH: ${{ parameters.VSCODE_ARCH }}
VSCODE_RUN_UNIT_TESTS: ${{ parameters.VSCODE_RUN_UNIT_TESTS }}
VSCODE_RUN_INTEGRATION_TESTS: ${{ parameters.VSCODE_RUN_INTEGRATION_TESTS }}
VSCODE_RUN_SMOKE_TESTS: ${{ parameters.VSCODE_RUN_SMOKE_TESTS }}
${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
PUBLISH_TASK_NAME: 1ES.PublishPipelineArtifact@1
- ${{ if ne(parameters.VSCODE_CIBUILD, true) }}:
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- task: DownloadPipelineArtifact@2
inputs:
artifact: unsigned_vscode_cli_win32_$(VSCODE_ARCH)_cli
patterns: "**"
path: $(Build.ArtifactStagingDirectory)/cli
displayName: Download VS Code CLI
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$ArtifactName = (gci -Path "$(Build.ArtifactStagingDirectory)/cli" | Select-Object -last 1).FullName
Expand-Archive -Path $ArtifactName -DestinationPath "$(Build.ArtifactStagingDirectory)/cli"
$AppProductJson = Get-Content -Raw -Path "$(Agent.BuildDirectory)\VSCode-win32-$(VSCODE_ARCH)\resources\app\product.json" | ConvertFrom-Json
$CliAppName = $AppProductJson.tunnelApplicationName
$AppName = $AppProductJson.applicationName
Move-Item -Path "$(Build.ArtifactStagingDirectory)/cli/$AppName.exe" -Destination "$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)/bin/$CliAppName.exe"
displayName: Move VS Code CLI
- task: UseDotNet@2
inputs:
version: 6.x
- task: EsrpCodeSigning@5
inputs:
UseMSIAuthentication: true
ConnectedServiceName: vscode-esrp
AppRegistrationClientId: $(ESRP_CLIENT_ID)
AppRegistrationTenantId: $(ESRP_TENANT_ID)
AuthAKVName: vscode-esrp
AuthSignCertName: esrp-sign
FolderPath: .
Pattern: noop
displayName: 'Install ESRP Tooling'
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$EsrpCodeSigningTool = (gci -directory -filter EsrpCodeSigning_* $(Agent.RootDirectory)\_tasks | Select-Object -last 1).FullName
$Version = (gci -directory $EsrpCodeSigningTool | Select-Object -last 1).FullName
echo "##vso[task.setvariable variable=EsrpCliDllPath]$Version\net6.0\esrpcli.dll"
displayName: Find ESRP CLI
- powershell: node build\azure-pipelines\common\sign $env:EsrpCliDllPath sign-windows $(CodeSigningFolderPath) '*.dll,*.exe,*.node'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign executables and shared libraries
- powershell: node build\azure-pipelines\common\sign $env:EsrpCliDllPath sign-windows-appx $(CodeSigningFolderPath) '*.ps1'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign Powershell scripts
- ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}:
- powershell: node build\azure-pipelines\common\sign $env:EsrpCliDllPath sign-windows-appx $(CodeSigningFolderPath) '*.appx'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Codesign context menu appx package
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$PackageJson = Get-Content -Raw -Path ..\VSCode-win32-$(VSCODE_ARCH)\resources\app\package.json | ConvertFrom-Json
$Version = $PackageJson.version
echo "##vso[task.setvariable variable=VSCODE_VERSION]$Version"
condition: succeededOrFailed()
displayName: Get product version
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$ArchivePath = ".build\win32-$(VSCODE_ARCH)\VSCode-win32-$(VSCODE_ARCH)-$(VSCODE_VERSION).zip"
New-Item -ItemType Directory -Path .build\win32-$(VSCODE_ARCH) -Force
exec { 7z.exe a -tzip $ArchivePath ..\VSCode-win32-$(VSCODE_ARCH)\* "-xr!CodeSignSummary*.md" }
echo "##vso[task.setvariable variable=CLIENT_PATH]$ArchivePath"
echo "Listing archive contents"
7z.exe l $ArchivePath
condition: and(succeededOrFailed(), eq(variables['BUILT_CLIENT'], 'true'))
displayName: Package client
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$ArchivePath = ".build\win32-$(VSCODE_ARCH)\vscode-server-win32-$(VSCODE_ARCH).zip"
New-Item -ItemType Directory -Path .build\win32-$(VSCODE_ARCH) -Force
exec { 7z.exe a -tzip $ArchivePath ..\vscode-server-win32-$(VSCODE_ARCH) }
echo "##vso[task.setvariable variable=SERVER_PATH]$ArchivePath"
echo "Listing archive contents"
7z.exe l $ArchivePath
condition: and(succeededOrFailed(), eq(variables['BUILT_SERVER'], 'true'))
displayName: Package server
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$ArchivePath = ".build\win32-$(VSCODE_ARCH)\vscode-server-win32-$(VSCODE_ARCH)-web.zip"
New-Item -ItemType Directory -Path .build\win32-$(VSCODE_ARCH) -Force
exec { 7z.exe a -tzip $ArchivePath ..\vscode-server-win32-$(VSCODE_ARCH)-web }
echo "##vso[task.setvariable variable=WEB_PATH]$ArchivePath"
echo "Listing archive contents"
7z.exe l $ArchivePath
condition: and(succeededOrFailed(), eq(variables['BUILT_WEB'], 'true'))
displayName: Package server (web)
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm exec -- npm-run-all -lp "gulp vscode-win32-$(VSCODE_ARCH)-system-setup -- --sign" "gulp vscode-win32-$(VSCODE_ARCH)-user-setup -- --sign" }
$SystemSetupPath = ".build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup-$(VSCODE_ARCH)-$(VSCODE_VERSION).exe"
$UserSetupPath = ".build\win32-$(VSCODE_ARCH)\user-setup\VSCodeUserSetup-$(VSCODE_ARCH)-$(VSCODE_VERSION).exe"
mv .build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup.exe $SystemSetupPath
mv .build\win32-$(VSCODE_ARCH)\user-setup\VSCodeSetup.exe $UserSetupPath
echo "##vso[task.setvariable variable=SYSTEM_SETUP_PATH]$SystemSetupPath"
echo "##vso[task.setvariable variable=USER_SETUP_PATH]$UserSetupPath"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Build setup packages (system, user)
- powershell: echo "##vso[task.setvariable variable=ARTIFACT_PREFIX]attempt$(System.JobAttempt)_"
condition: and(succeededOrFailed(), notIn(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues'))
displayName: Generate artifact prefix
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(CLIENT_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_client_win32_$(VSCODE_ARCH)_archive
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)
sbomPackageName: "VS Code Windows $(VSCODE_ARCH)"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['CLIENT_PATH'], ''))
displayName: Publish archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SERVER_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_server_win32_$(VSCODE_ARCH)_archive
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-win32-$(VSCODE_ARCH)
sbomPackageName: "VS Code Windows $(VSCODE_ARCH) Server"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['SERVER_PATH'], ''))
displayName: Publish server archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(WEB_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_web_win32_$(VSCODE_ARCH)_archive
sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-win32-$(VSCODE_ARCH)-web
sbomPackageName: "VS Code Windows $(VSCODE_ARCH) Web"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], ''))
displayName: Publish web server archive
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(SYSTEM_SETUP_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_client_win32_$(VSCODE_ARCH)_setup
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)
sbomPackageName: "VS Code Windows $(VSCODE_ARCH) System Setup"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['SYSTEM_SETUP_PATH'], ''))
displayName: Publish system setup
- task: 1ES.PublishPipelineArtifact@1
inputs:
targetPath: $(USER_SETUP_PATH)
artifactName: $(ARTIFACT_PREFIX)vscode_client_win32_$(VSCODE_ARCH)_user-setup
sbomBuildDropPath: $(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)
sbomPackageName: "VS Code Windows $(VSCODE_ARCH) User Setup"
sbomPackageVersion: $(Build.SourceVersion)
condition: and(succeededOrFailed(), ne(variables['USER_SETUP_PATH'], ''))
displayName: Publish user setup
================================================
FILE: build/azure-pipelines/win32/retry.ps1
================================================
function Retry
{
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=1)][scriptblock]$cmd
)
$retry = 0
while ($retry++ -lt 5) {
try {
& $cmd
return
} catch {
# noop
}
}
throw "Max retries reached"
}
================================================
FILE: build/azure-pipelines/win32/sdl-scan-win32.yml
================================================
parameters:
- name: VSCODE_ARCH
type: string
- name: VSCODE_QUALITY
type: string
steps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
- task: UsePythonVersion@0
inputs:
versionSpec: "3.x"
addToPath: true
- template: ../distro/download-distro.yml@self
- task: AzureKeyVault@2
displayName: "Azure Key Vault: Get Secrets"
inputs:
azureSubscription: vscode
KeyVaultName: vscode-build-secrets
SecretsFilter: "github-distro-mixin-password"
- powershell: node build/setup-npm-registry.js $env:NPM_REGISTRY
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Registry
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
# Set the private NPM registry to the global npmrc file
# so that authentication works for subfolders like build/, remote/, extensions/ etc
# which does not have their own .npmrc file
exec { npm config set registry "$env:NPM_REGISTRY" }
$NpmrcPath = (npm config get userconfig)
echo "##vso[task.setvariable variable=NPMRC_PATH]$NpmrcPath"
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM
- task: npmAuthenticate@0
inputs:
workingFile: $(NPMRC_PATH)
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
displayName: Setup NPM Authentication
- pwsh: |
$includes = @'
{
'target_defaults': {
'conditions': [
['OS=="win"', {
'msvs_settings': {
'VCCLCompilerTool': {
'AdditionalOptions': [
'/Zi',
'/FS'
],
},
'VCLinkerTool': {
'AdditionalOptions': [
'/profile'
]
}
}
}]
]
}
}
'@
if (!(Test-Path "~/.gyp")) {
mkdir "~/.gyp"
}
echo $includes > "~/.gyp/include.gypi"
displayName: Create include.gypi
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm ci }
env:
npm_config_arch: ${{ parameters.VSCODE_ARCH }}
npm_config_foreground_scripts: "true"
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
GITHUB_TOKEN: "$(github-distro-mixin-password)"
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: node build/azure-pipelines/distro/mixin-npm
displayName: Mixin distro node modules
- script: node build/azure-pipelines/distro/mixin-quality
displayName: Mixin distro quality
env:
VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }}
- powershell: npm run compile
displayName: Compile
- powershell: npm run gulp "vscode-symbols-win32-${{ parameters.VSCODE_ARCH }}"
env:
GITHUB_TOKEN: "$(github-distro-mixin-password)"
displayName: Download Symbols
- powershell: |
Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.exe"
Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.dll"
Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.node"
Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.pdb"
displayName: List files
- task: CopyFiles@2
displayName: 'Collect Symbols for API Scan'
inputs:
SourceFolder: $(Agent.BuildDirectory)
Contents: 'scanbin\**\*.pdb'
TargetFolder: '$(Agent.BuildDirectory)\symbols'
flattenFolders: true
condition: succeeded()
- task: APIScan@2
inputs:
softwareFolder: $(Agent.BuildDirectory)\scanbin
softwareName: 'vscode-client'
softwareVersionNum: '1'
symbolsFolder: 'srv*https://symweb.azurefd.net;$(Agent.BuildDirectory)\symbols'
isLargeApp: false
toolVersion: 'Latest'
azureSubscription: 'vscode-apiscan'
displayName: Run ApiScan
condition: succeeded()
env:
AzureServicesAuthConnectionString: RunAs=App;AppId=c0940da5-8bd3-4dd3-8af1-40774b50edbd;TenantId=72f988bf-86f1-41af-91ab-2d7cd011db47;ServiceConnectionId=3e55d992-b60d-414d-9071-e4fad359c748;
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- task: PublishSecurityAnalysisLogs@3
inputs:
ArtifactName: CodeAnalysisLogs
ArtifactType: Container
PublishProcessedResults: false
AllTools: true
# TSA Upload
- task: securedevelopmentteam.vss-secure-development-tools.build-task-uploadtotsa.TSAUpload@2
displayName: TSA Upload
continueOnError: true
inputs:
GdnPublishTsaOnboard: true
GdnPublishTsaConfigFile: '$(Build.SourcesDirectory)/build/azure-pipelines/config/tsaoptions.json'
================================================
FILE: build/buildfile.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* @param {string} name
* @returns {import('./lib/bundle').IEntryPoint}
*/
function createModuleDescription(name) {
return {
name
};
}
exports.workerEditor = createModuleDescription('vs/editor/common/services/editorWebWorkerMain');
exports.workerExtensionHost = createModuleDescription('vs/workbench/api/worker/extensionHostWorkerMain');
exports.workerNotebook = createModuleDescription('vs/workbench/contrib/notebook/common/services/notebookWebWorkerMain');
exports.workerLanguageDetection = createModuleDescription('vs/workbench/services/languageDetection/browser/languageDetectionWebWorkerMain');
exports.workerLocalFileSearch = createModuleDescription('vs/workbench/services/search/worker/localFileSearchMain');
exports.workerProfileAnalysis = createModuleDescription('vs/platform/profiling/electron-sandbox/profileAnalysisWorkerMain');
exports.workerOutputLinks = createModuleDescription('vs/workbench/contrib/output/common/outputLinkComputerMain');
exports.workerBackgroundTokenization = createModuleDescription('vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.workerMain');
exports.workbenchDesktop = [
createModuleDescription('vs/workbench/contrib/debug/node/telemetryApp'),
createModuleDescription('vs/platform/files/node/watcher/watcherMain'),
createModuleDescription('vs/platform/terminal/node/ptyHostMain'),
createModuleDescription('vs/workbench/api/node/extensionHostProcess'),
createModuleDescription('vs/workbench/workbench.desktop.main')
];
exports.workbenchWeb = createModuleDescription('vs/workbench/workbench.web.main');
exports.keyboardMaps = [
createModuleDescription('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.linux'),
createModuleDescription('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.darwin'),
createModuleDescription('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.win')
];
exports.code = [
// 'vs/code/electron-main/main' is not included here because it comes in via ./src/main.js
// 'vs/code/node/cli' is not included here because it comes in via ./src/cli.js
createModuleDescription('vs/code/node/cliProcessMain'),
createModuleDescription('vs/code/electron-utility/sharedProcess/sharedProcessMain'),
createModuleDescription('vs/code/electron-sandbox/processExplorer/processExplorerMain'),
createModuleDescription('vs/code/electron-sandbox/workbench/workbench'),
createModuleDescription('vs/code/electron-sandbox/processExplorer/processExplorer')
];
exports.codeWeb = createModuleDescription('vs/code/browser/workbench/workbench');
exports.codeServer = [
// 'vs/server/node/server.main' is not included here because it gets inlined via ./src/server-main.js
// 'vs/server/node/server.cli' is not included here because it gets inlined via ./src/server-cli.js
createModuleDescription('vs/workbench/api/node/extensionHostProcess'),
createModuleDescription('vs/platform/files/node/watcher/watcherMain'),
createModuleDescription('vs/platform/terminal/node/ptyHostMain')
];
exports.entrypoint = createModuleDescription;
================================================
FILE: build/builtin/.eslintrc
================================================
{
"env": {
"node": true,
"es6": true,
"browser": true
},
"rules": {
"no-console": 0,
"no-cond-assign": 0,
"no-unused-vars": 1,
"no-extra-semi": "warn",
"semi": "warn"
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
}
================================================
FILE: build/builtin/browser-main.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 fs = require('fs');
const path = require('path');
const os = require('os');
const { ipcRenderer } = require('electron');
const builtInExtensionsPath = path.join(__dirname, '..', '..', 'product.json');
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
/**
* @param {string} filePath
*/
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));
}
/**
* @param {string} filePath
* @param {any} obj
*/
function writeJson(filePath, obj) {
fs.writeFileSync(filePath, JSON.stringify(obj, null, 2));
}
/**
* @param {HTMLFormElement} form
* @param {string} id
* @param {string} title
* @param {string} value
* @param {boolean} checked
*/
function renderOption(form, id, title, value, checked) {
const input = document.createElement('input');
input.type = 'radio';
input.id = id;
input.name = 'choice';
input.value = value;
input.checked = !!checked;
form.appendChild(input);
const label = document.createElement('label');
label.setAttribute('for', id);
label.textContent = title;
form.appendChild(label);
return input;
}
/**
* @param {HTMLElement} el
* @param {any} state
*/
function render(el, state) {
/**
* @param {any} state
*/
function setState(state) {
try {
writeJson(controlFilePath, state.control);
} catch (err) {
console.error(err);
}
el.innerHTML = '';
render(el, state);
}
const ul = document.createElement('ul');
const { builtin, control } = state;
for (const ext of builtin) {
const controlState = control[ext.name] || 'marketplace';
const li = document.createElement('li');
ul.appendChild(li);
const name = document.createElement('code');
name.textContent = ext.name;
li.appendChild(name);
const form = document.createElement('form');
li.appendChild(form);
const marketplaceInput = renderOption(form, `marketplace-${ext.name}`, 'Marketplace', 'marketplace', controlState === 'marketplace');
marketplaceInput.onchange = function () {
control[ext.name] = 'marketplace';
setState({ builtin, control });
};
const disabledInput = renderOption(form, `disabled-${ext.name}`, 'Disabled', 'disabled', controlState === 'disabled');
disabledInput.onchange = function () {
control[ext.name] = 'disabled';
setState({ builtin, control });
};
let local = undefined;
if (controlState !== 'marketplace' && controlState !== 'disabled') {
local = controlState;
}
const localInput = renderOption(form, `local-${ext.name}`, 'Local', 'local', !!local);
localInput.onchange = async function () {
const result = await ipcRenderer.invoke('pickdir');
if (result) {
control[ext.name] = result;
setState({ builtin, control });
}
};
if (local) {
const localSpan = document.createElement('code');
localSpan.className = 'local';
localSpan.textContent = local;
form.appendChild(localSpan);
}
}
el.appendChild(ul);
}
function main() {
const el = document.getElementById('extensions');
const builtin = readJson(builtInExtensionsPath).builtInExtensions;
let control;
try {
control = readJson(controlFilePath);
} catch (err) {
control = {};
}
if (el) {
render(el, { builtin, control });
}
}
window.onload = main;
================================================
FILE: build/builtin/index.html
================================================
Manage Built-in Extensions
Built-in Extensions
================================================
FILE: build/builtin/main.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 { app, BrowserWindow, ipcMain, dialog } = require('electron');
const url = require('url');
const path = require('path');
let window = null;
ipcMain.handle('pickdir', async () => {
const result = await dialog.showOpenDialog(window, {
title: 'Choose Folder',
properties: ['openDirectory']
});
if (result.canceled || result.filePaths.length < 1) {
return undefined;
}
return result.filePaths[0];
});
app.once('ready', () => {
window = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableWebSQL: false
}
});
window.setMenuBarVisibility(false);
window.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true }));
// window.webContents.openDevTools();
window.once('closed', () => window = null);
});
app.on('window-all-closed', () => app.quit());
================================================
FILE: build/builtin/package.json
================================================
{
"name": "builtin",
"version": "0.1.0",
"main": "main.js"
}
================================================
FILE: build/checksums/electron.txt
================================================
c9b82c9f381742e839fea00aeb14f24519bcaf38a0f4eed25532191701f9535b *chromedriver-v34.3.2-darwin-arm64.zip
d556c1e2b06f1bf131e83c2fb981de755c28e1083a884d257eb964815be16b0c *chromedriver-v34.3.2-darwin-x64.zip
1cabad4f3303ac2ff172a9f22185f64944dbaa6fc68271609077158eaefdee35 *chromedriver-v34.3.2-linux-arm64.zip
4213ce52c72ef414179b5c5c22ae8423847ff030d438296bd6c2aac763930a7b *chromedriver-v34.3.2-linux-armv7l.zip
3c64c08221fdfc0f4be60ea8b1b126f2ecca45f60001b63778522f711022c6ea *chromedriver-v34.3.2-linux-x64.zip
e8388734d88e011cb6cd79795431de9206820749219d80565ee49d90501d2bf3 *chromedriver-v34.3.2-mas-arm64.zip
3ad1dd37bd6e0bb37e8503898db7aedd56bd5213e6d6760b05c3d11f4625062b *chromedriver-v34.3.2-mas-x64.zip
d567b481a0f5d88e84bba7718f89fb08f56363bfc4cb5914e1c2086358a5c252 *chromedriver-v34.3.2-win32-arm64.zip
df6732e9dc61cb20a3c0b2a2de453aac7e2bd54e7cbff43512afa614852c15fa *chromedriver-v34.3.2-win32-ia32.zip
dda0765c8d064924632e18cd152014ecd767f3808fc51c8249a053bfb7ca70a2 *chromedriver-v34.3.2-win32-x64.zip
1945f15caff98f2e0f1ee539c483d352fb8d4d0c13f342caa7abe247676d828c *electron-api.json
c078bbf727b3c3026f60e07a0f4643b85c06c581b54be017d0a6c284ba6772d3 *electron-v34.3.2-darwin-arm64-dsym-snapshot.zip
35f587754d6a3272606258386bf73688d63dd53c7e572d3a7cbaae6f3f60bdae *electron-v34.3.2-darwin-arm64-dsym.zip
08b14ee02c98353de3c738120dfd017322666e82b914a7f6de9b9888dcc5c0f0 *electron-v34.3.2-darwin-arm64-symbols.zip
2a4aa7e8fa30f229e465ebd18d3e4722e2b41529dc51a68a954d333a7e556ffe *electron-v34.3.2-darwin-arm64.zip
1509ccdeb80024f5e3edd5ecf804b4cef4e47ea2bd74e33ef0b39044b0ccf892 *electron-v34.3.2-darwin-x64-dsym-snapshot.zip
3bbe5d587c3f582ed8c126b0fb635cc02ad9a14d077b04892fe6f862092445b0 *electron-v34.3.2-darwin-x64-dsym.zip
fa7ece82e6ecaf1c94ed341e8ebff98e64687c68fe113f52cd9a21400302e22f *electron-v34.3.2-darwin-x64-symbols.zip
23938c62257a65a863ed7aa7c7966ba5f257a7d3dc16c78293e826962cc39c5c *electron-v34.3.2-darwin-x64.zip
0547eecf8ab538d74fa854f591ce8b888a3dbb339256d2db3038e7bb2c6dd929 *electron-v34.3.2-linux-arm64-debug.zip
676d0dc2b1c1c85c8b2abbb8cd5376ee22ecdb910493b910d9ae5a998532136a *electron-v34.3.2-linux-arm64-symbols.zip
774e4ccb39d553e5487994a9f8c60774a90f08cdb049ff65f3963fc27c969ff2 *electron-v34.3.2-linux-arm64.zip
0547eecf8ab538d74fa854f591ce8b888a3dbb339256d2db3038e7bb2c6dd929 *electron-v34.3.2-linux-armv7l-debug.zip
ba33bf53fcb35dea568a2795f5b23ecf46c218abe8258946611c72a1f42f716c *electron-v34.3.2-linux-armv7l-symbols.zip
73ae92c8fffb351d3a455569cf57ce9a3f676f42bf61939c613c607fe0fc3bfb *electron-v34.3.2-linux-armv7l.zip
e61a9a69dd7ea6f2687708a8e83516670cdea53c728226e598e2f6f1fad5b77b *electron-v34.3.2-linux-x64-debug.zip
f1a04df7fe67dd1cd29e7b87871525458d2eb24c0cf3b5835a1c56974707562a *electron-v34.3.2-linux-x64-symbols.zip
7b74c0c4fae82e27c7e9cbca13e9763e046113dba8737d3e27de9a0b300ac87e *electron-v34.3.2-linux-x64.zip
8571a6aa83e00925ceb39fdc5a45a9f6b9aa3d92fd84951c6f252ed723aea4ae *electron-v34.3.2-mas-arm64-dsym-snapshot.zip
477410c6f9a6c5eeaedf376058a02c2996fc0a334aa40eeec7d3734c09347f4d *electron-v34.3.2-mas-arm64-dsym.zip
c2e62dcd6630cb51b2d8e2869e74e47d29bda785521cea6e82e546d0fc58aabb *electron-v34.3.2-mas-arm64-symbols.zip
a1698e8546a062fd59b7f8e5507a7f3220fb00b347f2377de83fc9a07f7f3507 *electron-v34.3.2-mas-arm64.zip
741a24ac230a3651dca81d211f9f00b835c428a5ed0c5f67d370d4e88b62f8d6 *electron-v34.3.2-mas-x64-dsym-snapshot.zip
aeff97ec9e5c9e173ac89e38acd94476025c5640d5f27be1e8c2abd54398bab3 *electron-v34.3.2-mas-x64-dsym.zip
9f14b66b1d612ac66697288e8763171c388f7f200854871a5f0ab464a6a921c2 *electron-v34.3.2-mas-x64-symbols.zip
c979d7e7175f1e8e03ca187997d4c156b878189fc3611b347fadebcb16f3e027 *electron-v34.3.2-mas-x64.zip
f43c700641e8220205dd356952e32718d113cf530520c4ed7209b59851eac266 *electron-v34.3.2-win32-arm64-pdb.zip
3ba6e01c99bffac6b5dd3fd6f122ecdb571cf6f675dc5498c65050bd7a382ef8 *electron-v34.3.2-win32-arm64-symbols.zip
c23f84aabb09c24cd2ae759a547fdba4206af19a3bb0f4554a91cd9528648ad0 *electron-v34.3.2-win32-arm64-toolchain-profile.zip
9b9cb65d75a16782088b492f9ef3bb4d27525012b819c12bf29bd27e159d749b *electron-v34.3.2-win32-arm64.zip
1006e7af4c149114b5ebc3497617aaa6cd1bb0b131e0a225fd73709ff308f9c5 *electron-v34.3.2-win32-ia32-pdb.zip
1ecb6430cd04454f08f557c9579163f3552144bfcc0b67b768dad8868b5b891d *electron-v34.3.2-win32-ia32-symbols.zip
c23f84aabb09c24cd2ae759a547fdba4206af19a3bb0f4554a91cd9528648ad0 *electron-v34.3.2-win32-ia32-toolchain-profile.zip
d004fd5f853754001fafaec33e383d1950b30c935ee71b297ec1c9e084355e9b *electron-v34.3.2-win32-ia32.zip
4e0721552fd2f09e9466e88089af8b965f1bfbc4ae00a59aaf6245b1d1efabfd *electron-v34.3.2-win32-x64-pdb.zip
9dea812a7e7cd0fb18e5fed9a99db5531959a068c24d3c0ecedceb644cd3ffa0 *electron-v34.3.2-win32-x64-symbols.zip
c23f84aabb09c24cd2ae759a547fdba4206af19a3bb0f4554a91cd9528648ad0 *electron-v34.3.2-win32-x64-toolchain-profile.zip
1785e161420fb90d2331c26e50bba3413cae9625b7db3c8524ea02ade631efba *electron-v34.3.2-win32-x64.zip
722b304c31ddac58b0083d94a241c5276464f04bd8ea4fcbfd33051d197be103 *electron.d.ts
31ce159b2e47d1de5bc907d8e1c89726b0f2ba530ec2e9d7a8e5c723b1ccf6e0 *ffmpeg-v34.3.2-darwin-arm64.zip
565539bac64a6ee9cf6f188070f520210a1507341718f5dc388ac7c454b1e1d5 *ffmpeg-v34.3.2-darwin-x64.zip
6006ea0f46ab229feb2685be086b0fafd65981e2939dd2218a078459c75ab527 *ffmpeg-v34.3.2-linux-arm64.zip
9404ce2e85df7c40f809f2cf62c7af607de299839fe6b7ae978c3015500abcc8 *ffmpeg-v34.3.2-linux-armv7l.zip
79aec96898b7e2462826780ee0b52b9ab299dc662af333e128a34fd5ddae87f1 *ffmpeg-v34.3.2-linux-x64.zip
9190743c78210574faf5d5ecb82a00f8fa15e5f2253378cb925a99ca9d39961b *ffmpeg-v34.3.2-mas-arm64.zip
48915adcb1a6342efeda896035101300f0432c0304cfb38f2378e98c6309ebae *ffmpeg-v34.3.2-mas-x64.zip
745d5ef786de6d4a720475079836e2fda7b501cfcd255819485a47de5b24b74e *ffmpeg-v34.3.2-win32-arm64.zip
d0d86d60978439dc8ae4a723d4e4c1f853891d596bfd84033440a232fa762e2f *ffmpeg-v34.3.2-win32-ia32.zip
4441539fd8c9cbe79880ff1bade9bdc0c3744c33d7409130af6404e57ee401ff *ffmpeg-v34.3.2-win32-x64.zip
39edd1eeefe881aa75af0e438204e0b1c6e6724e34fa5819109276331c0c2c9a *hunspell_dictionaries.zip
20dd417536e5f4ebc01f480221284c0673729c27b082bc04e2922f16cd571719 *libcxx-objects-v34.3.2-linux-arm64.zip
7e53c5779c04f895f8282c0450ec4a63074d15a0e910e41006cfea133d0288af *libcxx-objects-v34.3.2-linux-armv7l.zip
92e2283c924ab523ffec3ea22513beaab6417f7fc3d570f57d51a1e1ceb7f510 *libcxx-objects-v34.3.2-linux-x64.zip
9bf3c6e8ad68f523fe086fada4148dd04e5bb0b9290d104873e66f2584a5cf50 *libcxx_headers.zip
34e4b44f9c5e08b557a2caed55456ce7690abab910196a783a2a47b58d2b9ac9 *libcxxabi_headers.zip
11f67635e6659f9188198e4086c51b89890b61a22f6c17c99eff35595ee8f51d *mksnapshot-v34.3.2-darwin-arm64.zip
c0add9ef4ac27c73fa043d04b4c9635fd3fd9f5c16d7a03e961864ba05252813 *mksnapshot-v34.3.2-darwin-x64.zip
6262adf86a340d8d28059937b01ef1117b93212e945fddbceea5c18d7e7c64f0 *mksnapshot-v34.3.2-linux-arm64-x64.zip
f7db8ebe91a1cc8d24ef6aad12949a18d8e4975ac296e3e5e9ecd88c9bccb143 *mksnapshot-v34.3.2-linux-armv7l-x64.zip
6642038e86bda362980ff1c8973a404e2b02efdd87de9e35b650fc1e743833da *mksnapshot-v34.3.2-linux-x64.zip
15883bf8e8cd737c3682d1e719d7cbac92f50b525681aac324dca876861dfc7d *mksnapshot-v34.3.2-mas-arm64.zip
4da23a950bfcc377ef21c37d496017ab4c36da03f3b41049ac114042c42608ce *mksnapshot-v34.3.2-mas-x64.zip
fab59573d3c2f9bdf31146a1896d24ac0c51f736aad86d2f3c7ecef13c05a7fd *mksnapshot-v34.3.2-win32-arm64-x64.zip
66f25e07c6f8d5d2009577a129440255a3baf63c929a5b60b2e77cd52e46105b *mksnapshot-v34.3.2-win32-ia32.zip
8168bfbf61882cfac80aed1e71e364e1c7f2fccd11eac298e6abade8b46894ea *mksnapshot-v34.3.2-win32-x64.zip
================================================
FILE: build/checksums/nodejs.txt
================================================
1f15b7ed18a580af31cf32bc126572292d820f547bf55bf9cdce08041a24e1d9 node-v20.18.3-darwin-arm64.tar.gz
ba668f64df9239843fefcef095ee539f5ac5aa1b0fc15a71f1ecca16abedec7a node-v20.18.3-darwin-x64.tar.gz
93a9df19238adfaa289f4784041d03edaf2fdd89fbb247faffca2fe4a1000703 node-v20.18.3-linux-arm64.tar.gz
8a84eb34287db6a273066934d7195e429f57b91686b62fc19497210204a2b3de node-v20.18.3-linux-armv7l.tar.gz
9fc3952da39b20d1fcfdb777b198cc035485afbbb1004b4df93f35245d61151e node-v20.18.3-linux-x64.tar.gz
4258e333f4b95060681d61bffa762542a8068547d3dffebe57c575b38d380dda win-arm64/node.exe
528a9aa64888a2a3ba71c6aea89434dd5ab5cb3caa9f0f31345cf5facf685ab0 win-x64/node.exe
================================================
FILE: build/checksums/vscode-sysroot.txt
================================================
0de422a81683cf9e8cf875dbd1e0c27545ac3c775b2d53015daf3ca2b31d3f15 aarch64-linux-gnu-glibc-2.28.tar.gz
7aea163f7fad8cc50000c86b5108be880121d35e2f55d016ef8c96bbe54129eb arm-rpi-linux-gnueabihf-glibc-2.28.tar.gz
dbb927408393041664a020661f2641c9785741be3d29b050b9dac58980967784 x86_64-linux-gnu-glibc-2.28.tar.gz
================================================
FILE: build/darwin/create-universal-app.js
================================================
"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 path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const minimatch_1 = __importDefault(require("minimatch"));
const vscode_universal_bundler_1 = require("vscode-universal-bundler");
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
async function main(buildDir) {
const arch = process.env['VSCODE_ARCH'];
if (!buildDir) {
throw new Error('Build dir not provided');
}
const product = JSON.parse(fs_1.default.readFileSync(path_1.default.join(root, 'product.json'), 'utf8'));
const appName = product.nameLong + '.app';
const x64AppPath = path_1.default.join(buildDir, 'VSCode-darwin-x64', appName);
const arm64AppPath = path_1.default.join(buildDir, 'VSCode-darwin-arm64', appName);
const asarRelativePath = path_1.default.join('Contents', 'Resources', 'app', 'node_modules.asar');
const outAppPath = path_1.default.join(buildDir, `VSCode-darwin-${arch}`, appName);
const productJsonPath = path_1.default.resolve(outAppPath, 'Contents', 'Resources', 'app', 'product.json');
const filesToSkip = [
'**/CodeResources',
'**/Credits.rtf',
'**/policies/{*.mobileconfig,**/*.plist}',
// TODO: Should we consider expanding this to other files in this area?
'**/node_modules/@parcel/node-addon-api/nothing.target.mk'
];
await (0, vscode_universal_bundler_1.makeUniversalApp)({
x64AppPath,
arm64AppPath,
asarPath: asarRelativePath,
outAppPath,
force: true,
mergeASARs: true,
x64ArchFiles: '*/kerberos.node',
filesToSkipComparison: (file) => {
for (const expected of filesToSkip) {
if ((0, minimatch_1.default)(file, expected)) {
return true;
}
}
return false;
}
});
const productJson = JSON.parse(fs_1.default.readFileSync(productJsonPath, 'utf8'));
Object.assign(productJson, {
darwinUniversalAssetId: 'darwin-universal'
});
fs_1.default.writeFileSync(productJsonPath, JSON.stringify(productJson, null, '\t'));
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}
//# sourceMappingURL=create-universal-app.js.map
================================================
FILE: build/darwin/create-universal-app.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import path from 'path';
import fs from 'fs';
import minimatch from 'minimatch';
import { makeUniversalApp } from 'vscode-universal-bundler';
const root = path.dirname(path.dirname(__dirname));
async function main(buildDir?: string) {
const arch = process.env['VSCODE_ARCH'];
if (!buildDir) {
throw new Error('Build dir not provided');
}
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
const appName = product.nameLong + '.app';
const x64AppPath = path.join(buildDir, 'VSCode-darwin-x64', appName);
const arm64AppPath = path.join(buildDir, 'VSCode-darwin-arm64', appName);
const asarRelativePath = path.join('Contents', 'Resources', 'app', 'node_modules.asar');
const outAppPath = path.join(buildDir, `VSCode-darwin-${arch}`, appName);
const productJsonPath = path.resolve(outAppPath, 'Contents', 'Resources', 'app', 'product.json');
const filesToSkip = [
'**/CodeResources',
'**/Credits.rtf',
'**/policies/{*.mobileconfig,**/*.plist}',
// TODO: Should we consider expanding this to other files in this area?
'**/node_modules/@parcel/node-addon-api/nothing.target.mk'
];
await makeUniversalApp({
x64AppPath,
arm64AppPath,
asarPath: asarRelativePath,
outAppPath,
force: true,
mergeASARs: true,
x64ArchFiles: '*/kerberos.node',
filesToSkipComparison: (file: string) => {
for (const expected of filesToSkip) {
if (minimatch(file, expected)) {
return true;
}
}
return false;
}
});
const productJson = JSON.parse(fs.readFileSync(productJsonPath, 'utf8'));
Object.assign(productJson, {
darwinUniversalAssetId: 'darwin-universal'
});
fs.writeFileSync(productJsonPath, JSON.stringify(productJson, null, '\t'));
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/darwin/sign.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const electron_osx_sign_1 = __importDefault(require("electron-osx-sign"));
const cross_spawn_promise_1 = require("@malept/cross-spawn-promise");
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
function getElectronVersion() {
const npmrc = fs_1.default.readFileSync(path_1.default.join(root, '.npmrc'), 'utf8');
const target = /^target="(.*)"$/m.exec(npmrc)[1];
return target;
}
async function main(buildDir) {
const tempDir = process.env['AGENT_TEMPDIRECTORY'];
const arch = process.env['VSCODE_ARCH'];
const identity = process.env['CODESIGN_IDENTITY'];
if (!buildDir) {
throw new Error('$AGENT_BUILDDIRECTORY not set');
}
if (!tempDir) {
throw new Error('$AGENT_TEMPDIRECTORY not set');
}
const product = JSON.parse(fs_1.default.readFileSync(path_1.default.join(root, 'product.json'), 'utf8'));
const baseDir = path_1.default.dirname(__dirname);
const appRoot = path_1.default.join(buildDir, `VSCode-darwin-${arch}`);
const appName = product.nameLong + '.app';
const appFrameworkPath = path_1.default.join(appRoot, appName, 'Contents', 'Frameworks');
const helperAppBaseName = product.nameShort;
const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app';
const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app';
const pluginHelperAppName = helperAppBaseName + ' Helper (Plugin).app';
const infoPlistPath = path_1.default.resolve(appRoot, appName, 'Contents', 'Info.plist');
const defaultOpts = {
app: path_1.default.join(appRoot, appName),
platform: 'darwin',
entitlements: path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
'entitlements-inherit': path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
hardenedRuntime: true,
'pre-auto-entitlements': false,
'pre-embed-provisioning-profile': false,
keychain: path_1.default.join(tempDir, 'buildagent.keychain'),
version: getElectronVersion(),
identity,
'gatekeeper-assess': false
};
const appOpts = {
...defaultOpts,
// TODO(deepak1556): Incorrectly declared type in electron-osx-sign
ignore: (filePath) => {
return filePath.includes(gpuHelperAppName) ||
filePath.includes(rendererHelperAppName) ||
filePath.includes(pluginHelperAppName);
}
};
const gpuHelperOpts = {
...defaultOpts,
app: path_1.default.join(appFrameworkPath, gpuHelperAppName),
entitlements: path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'),
'entitlements-inherit': path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'),
};
const rendererHelperOpts = {
...defaultOpts,
app: path_1.default.join(appFrameworkPath, rendererHelperAppName),
entitlements: path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'),
'entitlements-inherit': path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'),
};
const pluginHelperOpts = {
...defaultOpts,
app: path_1.default.join(appFrameworkPath, pluginHelperAppName),
entitlements: path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'),
'entitlements-inherit': path_1.default.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'),
};
// Only overwrite plist entries for x64 and arm64 builds,
// universal will get its copy from the x64 build.
if (arch !== 'universal') {
await (0, cross_spawn_promise_1.spawn)('plutil', [
'-insert',
'NSAppleEventsUsageDescription',
'-string',
'An application in Visual Studio Code wants to use AppleScript.',
`${infoPlistPath}`
]);
await (0, cross_spawn_promise_1.spawn)('plutil', [
'-replace',
'NSMicrophoneUsageDescription',
'-string',
'An application in Visual Studio Code wants to use the Microphone.',
`${infoPlistPath}`
]);
await (0, cross_spawn_promise_1.spawn)('plutil', [
'-replace',
'NSCameraUsageDescription',
'-string',
'An application in Visual Studio Code wants to use the Camera.',
`${infoPlistPath}`
]);
}
await electron_osx_sign_1.default.signAsync(gpuHelperOpts);
await electron_osx_sign_1.default.signAsync(rendererHelperOpts);
await electron_osx_sign_1.default.signAsync(pluginHelperOpts);
await electron_osx_sign_1.default.signAsync(appOpts);
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}
//# sourceMappingURL=sign.js.map
================================================
FILE: build/darwin/sign.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import codesign from 'electron-osx-sign';
import { spawn } from '@malept/cross-spawn-promise';
const root = path.dirname(path.dirname(__dirname));
function getElectronVersion(): string {
const npmrc = fs.readFileSync(path.join(root, '.npmrc'), 'utf8');
const target = /^target="(.*)"$/m.exec(npmrc)![1];
return target;
}
async function main(buildDir?: string): Promise {
const tempDir = process.env['AGENT_TEMPDIRECTORY'];
const arch = process.env['VSCODE_ARCH'];
const identity = process.env['CODESIGN_IDENTITY'];
if (!buildDir) {
throw new Error('$AGENT_BUILDDIRECTORY not set');
}
if (!tempDir) {
throw new Error('$AGENT_TEMPDIRECTORY not set');
}
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
const baseDir = path.dirname(__dirname);
const appRoot = path.join(buildDir, `VSCode-darwin-${arch}`);
const appName = product.nameLong + '.app';
const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks');
const helperAppBaseName = product.nameShort;
const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app';
const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app';
const pluginHelperAppName = helperAppBaseName + ' Helper (Plugin).app';
const infoPlistPath = path.resolve(appRoot, appName, 'Contents', 'Info.plist');
const defaultOpts: codesign.SignOptions = {
app: path.join(appRoot, appName),
platform: 'darwin',
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
hardenedRuntime: true,
'pre-auto-entitlements': false,
'pre-embed-provisioning-profile': false,
keychain: path.join(tempDir, 'buildagent.keychain'),
version: getElectronVersion(),
identity,
'gatekeeper-assess': false
};
const appOpts = {
...defaultOpts,
// TODO(deepak1556): Incorrectly declared type in electron-osx-sign
ignore: (filePath: string) => {
return filePath.includes(gpuHelperAppName) ||
filePath.includes(rendererHelperAppName) ||
filePath.includes(pluginHelperAppName);
}
};
const gpuHelperOpts: codesign.SignOptions = {
...defaultOpts,
app: path.join(appFrameworkPath, gpuHelperAppName),
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'),
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'),
};
const rendererHelperOpts: codesign.SignOptions = {
...defaultOpts,
app: path.join(appFrameworkPath, rendererHelperAppName),
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'),
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'),
};
const pluginHelperOpts: codesign.SignOptions = {
...defaultOpts,
app: path.join(appFrameworkPath, pluginHelperAppName),
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'),
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'),
};
// Only overwrite plist entries for x64 and arm64 builds,
// universal will get its copy from the x64 build.
if (arch !== 'universal') {
await spawn('plutil', [
'-insert',
'NSAppleEventsUsageDescription',
'-string',
'An application in Visual Studio Code wants to use AppleScript.',
`${infoPlistPath}`
]);
await spawn('plutil', [
'-replace',
'NSMicrophoneUsageDescription',
'-string',
'An application in Visual Studio Code wants to use the Microphone.',
`${infoPlistPath}`
]);
await spawn('plutil', [
'-replace',
'NSCameraUsageDescription',
'-string',
'An application in Visual Studio Code wants to use the Camera.',
`${infoPlistPath}`
]);
}
await codesign.signAsync(gpuHelperOpts);
await codesign.signAsync(rendererHelperOpts);
await codesign.signAsync(pluginHelperOpts);
await codesign.signAsync(appOpts as any);
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/darwin/verify-macho.js
================================================
"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 path_1 = __importDefault(require("path"));
const promises_1 = require("fs/promises");
const cross_spawn_promise_1 = require("@malept/cross-spawn-promise");
const MACHO_PREFIX = 'Mach-O ';
const MACHO_64_MAGIC_LE = 0xfeedfacf;
const MACHO_UNIVERSAL_MAGIC_LE = 0xbebafeca;
const MACHO_ARM64_CPU_TYPE = new Set([
0x0c000001,
0x0100000c,
]);
const MACHO_X86_64_CPU_TYPE = new Set([
0x07000001,
0x01000007,
]);
async function read(file, buf, offset, length, position) {
let filehandle;
try {
filehandle = await (0, promises_1.open)(file);
await filehandle.read(buf, offset, length, position);
}
finally {
await filehandle?.close();
}
}
async function checkMachOFiles(appPath, arch) {
const visited = new Set();
const invalidFiles = [];
const header = Buffer.alloc(8);
const file_header_entry_size = 20;
const checkx86_64Arch = (arch === 'x64');
const checkArm64Arch = (arch === 'arm64');
const checkUniversalArch = (arch === 'universal');
const traverse = async (p) => {
p = await (0, promises_1.realpath)(p);
if (visited.has(p)) {
return;
}
visited.add(p);
const info = await (0, promises_1.stat)(p);
if (info.isSymbolicLink()) {
return;
}
if (info.isFile()) {
let fileOutput = '';
try {
fileOutput = await (0, cross_spawn_promise_1.spawn)('file', ['--brief', '--no-pad', p]);
}
catch (e) {
if (e instanceof cross_spawn_promise_1.ExitCodeError) {
/* silently accept error codes from "file" */
}
else {
throw e;
}
}
if (fileOutput.startsWith(MACHO_PREFIX)) {
console.log(`Verifying architecture of ${p}`);
read(p, header, 0, 8, 0).then(_ => {
const header_magic = header.readUInt32LE();
if (header_magic === MACHO_64_MAGIC_LE) {
const cpu_type = header.readUInt32LE(4);
if (checkUniversalArch) {
invalidFiles.push(p);
}
else if (checkArm64Arch && !MACHO_ARM64_CPU_TYPE.has(cpu_type)) {
invalidFiles.push(p);
}
else if (checkx86_64Arch && !MACHO_X86_64_CPU_TYPE.has(cpu_type)) {
invalidFiles.push(p);
}
}
else if (header_magic === MACHO_UNIVERSAL_MAGIC_LE) {
const num_binaries = header.readUInt32BE(4);
assert_1.default.equal(num_binaries, 2);
const file_entries_size = file_header_entry_size * num_binaries;
const file_entries = Buffer.alloc(file_entries_size);
read(p, file_entries, 0, file_entries_size, 8).then(_ => {
for (let i = 0; i < num_binaries; i++) {
const cpu_type = file_entries.readUInt32LE(file_header_entry_size * i);
if (!MACHO_ARM64_CPU_TYPE.has(cpu_type) && !MACHO_X86_64_CPU_TYPE.has(cpu_type)) {
invalidFiles.push(p);
}
}
});
}
});
}
}
if (info.isDirectory()) {
for (const child of await (0, promises_1.readdir)(p)) {
await traverse(path_1.default.resolve(p, child));
}
}
};
await traverse(appPath);
return invalidFiles;
}
const archToCheck = process.argv[2];
(0, assert_1.default)(process.env['APP_PATH'], 'APP_PATH not set');
(0, assert_1.default)(archToCheck === 'x64' || archToCheck === 'arm64' || archToCheck === 'universal', `Invalid architecture ${archToCheck} to check`);
checkMachOFiles(process.env['APP_PATH'], archToCheck).then(invalidFiles => {
if (invalidFiles.length > 0) {
console.error('\x1b[31mThe following files are built for the wrong architecture:\x1b[0m');
for (const file of invalidFiles) {
console.error(`\x1b[31m${file}\x1b[0m`);
}
process.exit(1);
}
else {
console.log('\x1b[32mAll files are valid\x1b[0m');
}
}).catch(err => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=verify-macho.js.map
================================================
FILE: build/darwin/verify-macho.ts
================================================
/*---------------------------------------------------------------------------------------------
* 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 path from 'path';
import { open, stat, readdir, realpath } from 'fs/promises';
import { spawn, ExitCodeError } from '@malept/cross-spawn-promise';
const MACHO_PREFIX = 'Mach-O ';
const MACHO_64_MAGIC_LE = 0xfeedfacf;
const MACHO_UNIVERSAL_MAGIC_LE = 0xbebafeca;
const MACHO_ARM64_CPU_TYPE = new Set([
0x0c000001,
0x0100000c,
]);
const MACHO_X86_64_CPU_TYPE = new Set([
0x07000001,
0x01000007,
]);
async function read(file: string, buf: Buffer, offset: number, length: number, position: number) {
let filehandle;
try {
filehandle = await open(file);
await filehandle.read(buf, offset, length, position);
} finally {
await filehandle?.close();
}
}
async function checkMachOFiles(appPath: string, arch: string) {
const visited = new Set();
const invalidFiles: string[] = [];
const header = Buffer.alloc(8);
const file_header_entry_size = 20;
const checkx86_64Arch = (arch === 'x64');
const checkArm64Arch = (arch === 'arm64');
const checkUniversalArch = (arch === 'universal');
const traverse = async (p: string) => {
p = await realpath(p);
if (visited.has(p)) {
return;
}
visited.add(p);
const info = await stat(p);
if (info.isSymbolicLink()) {
return;
}
if (info.isFile()) {
let fileOutput = '';
try {
fileOutput = await spawn('file', ['--brief', '--no-pad', p]);
} catch (e) {
if (e instanceof ExitCodeError) {
/* silently accept error codes from "file" */
} else {
throw e;
}
}
if (fileOutput.startsWith(MACHO_PREFIX)) {
console.log(`Verifying architecture of ${p}`);
read(p, header, 0, 8, 0).then(_ => {
const header_magic = header.readUInt32LE();
if (header_magic === MACHO_64_MAGIC_LE) {
const cpu_type = header.readUInt32LE(4);
if (checkUniversalArch) {
invalidFiles.push(p);
} else if (checkArm64Arch && !MACHO_ARM64_CPU_TYPE.has(cpu_type)) {
invalidFiles.push(p);
} else if (checkx86_64Arch && !MACHO_X86_64_CPU_TYPE.has(cpu_type)) {
invalidFiles.push(p);
}
} else if (header_magic === MACHO_UNIVERSAL_MAGIC_LE) {
const num_binaries = header.readUInt32BE(4);
assert.equal(num_binaries, 2);
const file_entries_size = file_header_entry_size * num_binaries;
const file_entries = Buffer.alloc(file_entries_size);
read(p, file_entries, 0, file_entries_size, 8).then(_ => {
for (let i = 0; i < num_binaries; i++) {
const cpu_type = file_entries.readUInt32LE(file_header_entry_size * i);
if (!MACHO_ARM64_CPU_TYPE.has(cpu_type) && !MACHO_X86_64_CPU_TYPE.has(cpu_type)) {
invalidFiles.push(p);
}
}
});
}
});
}
}
if (info.isDirectory()) {
for (const child of await readdir(p)) {
await traverse(path.resolve(p, child));
}
}
};
await traverse(appPath);
return invalidFiles;
}
const archToCheck = process.argv[2];
assert(process.env['APP_PATH'], 'APP_PATH not set');
assert(archToCheck === 'x64' || archToCheck === 'arm64' || archToCheck === 'universal', `Invalid architecture ${archToCheck} to check`);
checkMachOFiles(process.env['APP_PATH'], archToCheck).then(invalidFiles => {
if (invalidFiles.length > 0) {
console.error('\x1b[31mThe following files are built for the wrong architecture:\x1b[0m');
for (const file of invalidFiles) {
console.error(`\x1b[31m${file}\x1b[0m`);
}
process.exit(1);
} else {
console.log('\x1b[32mAll files are valid\x1b[0m');
}
}).catch(err => {
console.error(err);
process.exit(1);
});
================================================
FILE: build/eslint.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const es = require('event-stream');
const vfs = require('vinyl-fs');
const { eslintFilter } = require('./filters');
function eslint() {
const eslint = require('./gulp-eslint');
return vfs
.src(eslintFilter, { base: '.', follow: true, allowEmpty: true })
.pipe(
eslint((results) => {
if (results.warningCount > 0 || results.errorCount > 0) {
throw new Error('eslint failed with warnings and/or errors');
}
})
).pipe(es.through(function () { /* noop, important for the stream to end */ }));
}
if (require.main === module) {
eslint().on('error', (err) => {
console.error();
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/filters.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Hygiene works by creating cascading subsets of all our files and
* passing them through a sequence of checks. Here are the current subsets,
* named according to the checks performed on them. Each subset contains
* the following one, as described in mathematical notation:
*
* all ⊃ eol ⊇ indentation ⊃ copyright ⊃ typescript
*/
const { readFileSync } = require('fs');
const { join } = require('path');
module.exports.all = [
'*',
'build/**/*',
'extensions/**/*',
'scripts/**/*',
'src/**/*',
'test/**/*',
'!cli/**/*',
'!out*/**',
'!test/**/out/**',
'!**/node_modules/**',
];
module.exports.unicodeFilter = [
'**',
'!**/ThirdPartyNotices.txt',
'!**/ThirdPartyNotices.cli.txt',
'!**/LICENSE.{txt,rtf}',
'!LICENSES.chromium.html',
'!**/LICENSE',
'!**/*.{dll,exe,png,bmp,jpg,scpt,cur,ttf,woff,eot,template,ico,icns,opus,wasm}',
'!**/test/**',
'!**/*.test.ts',
'!**/*.{d.ts,json,md}',
'!**/*.mp3',
'!build/win32/**',
'!extensions/markdown-language-features/notebook-out/*.js',
'!extensions/markdown-math/notebook-out/**',
'!extensions/ipynb/notebook-out/**',
'!extensions/notebook-renderers/renderer-out/**',
'!extensions/php-language-features/src/features/phpGlobalFunctions.ts',
'!extensions/terminal-suggest/src/completions/upstream/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/dist/**',
'!extensions/**/out/**',
'!extensions/**/snippets/**',
'!extensions/**/colorize-fixtures/**',
'!extensions/terminal-suggest/src/shell/fishBuiltinsCache.ts',
'!src/vs/base/browser/dompurify/**',
'!src/vs/workbench/services/keybinding/browser/keyboardLayouts/**',
];
module.exports.indentationFilter = [
'**',
// except specific files
'!**/ThirdPartyNotices.txt',
'!**/ThirdPartyNotices.cli.txt',
'!**/LICENSE.{txt,rtf}',
'!LICENSES.chromium.html',
'!**/LICENSE',
'!**/*.mp3',
'!src/vs/loader.js',
'!src/vs/base/browser/dompurify/*',
'!src/vs/base/common/marked/marked.js',
'!src/vs/base/common/semver/semver.js',
'!src/vs/base/node/terminateProcess.sh',
'!src/vs/base/node/cpuUsage.sh',
'!src/vs/editor/common/languages/highlights/*.scm',
'!src/vs/editor/common/languages/injections/*.scm',
'!test/unit/assert.js',
'!resources/linux/snap/electron-launch',
'!build/ext.js',
'!build/npm/gyp/patches/gyp_spectre_mitigation_support.patch',
'!product.overrides.json',
// except specific folders
'!test/automation/out/**',
'!test/monaco/out/**',
'!test/smoke/out/**',
'!extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts',
'!extensions/terminal-suggest/src/shell/fishBuiltinsCache.ts',
'!extensions/terminal-suggest/src/completions/upstream/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/typescript-language-features/resources/walkthroughs/**',
'!extensions/typescript-language-features/package-manager/node-maintainer/**',
'!extensions/markdown-math/notebook-out/**',
'!extensions/ipynb/notebook-out/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!build/monaco/**',
'!build/win32/**',
// except multiple specific files
'!**/package.json',
'!**/package-lock.json',
// except multiple specific folders
'!**/codicon/**',
'!**/fixtures/**',
'!**/lib/**',
'!extensions/**/dist/**',
'!extensions/**/out/**',
'!extensions/**/snippets/**',
'!extensions/**/syntaxes/**',
'!extensions/**/themes/**',
'!extensions/**/colorize-fixtures/**',
// except specific file types
'!src/vs/*/**/*.d.ts',
'!src/typings/**/*.d.ts',
'!extensions/**/*.d.ts',
'!**/*.{svg,exe,png,bmp,jpg,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,psm1,template,yaml,yml,d.ts.recipe,ico,icns,plist,opus,admx,adml,wasm}',
'!build/{lib,download,linux,darwin}/**/*.js',
'!build/**/*.sh',
'!build/azure-pipelines/**/*.js',
'!build/azure-pipelines/**/*.config',
'!**/Dockerfile',
'!**/Dockerfile.*',
'!**/*.Dockerfile',
'!**/*.dockerfile',
// except for built files
'!extensions/markdown-language-features/media/*.js',
'!extensions/markdown-language-features/notebook-out/*.js',
'!extensions/markdown-math/notebook-out/*.js',
'!extensions/ipynb/notebook-out/**',
'!extensions/notebook-renderers/renderer-out/*.js',
'!extensions/simple-browser/media/*.js',
];
module.exports.copyrightFilter = [
'**',
'!**/*.desktop',
'!**/*.json',
'!**/*.html',
'!**/*.template',
'!**/*.md',
'!**/*.bat',
'!**/*.cmd',
'!**/*.ico',
'!**/*.opus',
'!**/*.mp3',
'!**/*.icns',
'!**/*.xml',
'!**/*.sh',
'!**/*.zsh',
'!**/*.fish',
'!**/*.txt',
'!**/*.xpm',
'!**/*.opts',
'!**/*.disabled',
'!**/*.code-workspace',
'!**/*.js.map',
'!**/*.wasm',
'!build/**/*.init',
'!build/linux/libcxx-fetcher.*',
'!resources/linux/snap/snapcraft.yaml',
'!resources/win32/bin/code.js',
'!resources/completions/**',
'!extensions/configuration-editing/build/inline-allOf.ts',
'!extensions/markdown-language-features/media/highlight.css',
'!extensions/markdown-math/notebook-out/**',
'!extensions/ipynb/notebook-out/**',
'!extensions/simple-browser/media/codicon.css',
'!extensions/terminal-suggest/src/completions/upstream/**',
'!extensions/typescript-language-features/node-maintainer/**',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*',
];
module.exports.tsFormattingFilter = [
'src/**/*.ts',
'test/**/*.ts',
'extensions/**/*.ts',
'!src/vs/*/**/*.d.ts',
'!src/typings/**/*.d.ts',
'!extensions/**/*.d.ts',
'!**/fixtures/**',
'!**/typings/**',
'!**/node_modules/**',
'!extensions/**/colorize-fixtures/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/*.test.ts',
'!extensions/html-language-features/server/lib/jquery.d.ts',
'!extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts',
'!extensions/terminal-suggest/src/shell/fishBuiltinsCache.ts',
];
module.exports.eslintFilter = [
'**/*.js',
'**/*.cjs',
'**/*.mjs',
'**/*.ts',
'.eslint-plugin-local/**/*.ts',
...readFileSync(join(__dirname, '..', '.eslint-ignore'))
.toString()
.split(/\r\n|\n/)
.filter(line => line && !line.startsWith('#'))
.map(line => line.startsWith('!') ? line.slice(1) : `!${line}`)
];
module.exports.stylelintFilter = [
'src/**/*.css'
];
================================================
FILE: build/gulp-eslint.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 { ESLint } = require('eslint');
const { Transform } = require('stream');
const { relative } = require('path');
const fancyLog = require('fancy-log');
/**
* @param {Function} action - A function to handle all ESLint results
* @returns {stream} gulp file stream
*/
function eslint(action) {
const linter = new ESLint({});
const formatter = linter.loadFormatter('compact');
const results = [];
results.errorCount = 0;
results.warningCount = 0;
return transform(
async (file, enc, cb) => {
const filePath = relative(process.cwd(), file.path);
if (file.isNull()) {
cb(null, file);
return;
}
if (file.isStream()) {
cb(new Error('vinyl files with Stream contents are not supported'));
return;
}
try {
// TODO: Should this be checked?
if (await linter.isPathIgnored(filePath)) {
cb(null, file);
return;
}
const result = (await linter.lintText(file.contents.toString(), { filePath }))[0];
results.push(result);
results.errorCount += result.errorCount;
results.warningCount += result.warningCount;
const message = (await formatter).format([result]);
if (message) {
fancyLog(message);
}
cb(null, file);
} catch (error) {
cb(error);
}
},
(done) => {
try {
action(results);
done();
} catch (error) {
done(error);
}
});
}
function transform(transform, flush) {
return new Transform({
objectMode: true,
transform,
flush
});
}
module.exports = eslint;
================================================
FILE: build/gulpfile.cli.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 { promises: fs, 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 root = 'cli';
const rootAbs = path.resolve(__dirname, '..', root);
const src = `${root}/src`;
const platformOpensslDirName =
process.platform === 'win32' ? (
process.arch === 'arm64'
? 'arm64-windows-static-md'
: 'x64-windows-static-md')
: process.platform === 'darwin' ? (
process.arch === 'arm64'
? 'arm64-osx'
: 'x64-osx')
: (process.arch === 'arm64'
? 'arm64-linux'
: process.arch === 'arm'
? 'arm-linux'
: 'x64-linux');
const platformOpensslDir = path.join(rootAbs, 'openssl', 'package', 'out', platformOpensslDirName);
const hasLocalRust = (() => {
/** @type boolean | undefined */
let result = undefined;
return () => {
if (result !== undefined) {
return result;
}
try {
const r = cp.spawnSync('cargo', ['--version']);
result = r.status === 0;
} catch (e) {
result = false;
}
return result;
};
})();
const debounceEsStream = (fn, duration = 100) => {
let handle = undefined;
let pending = [];
const sendAll = (pending) => (event, ...args) => {
for (const stream of pending) {
pending.emit(event, ...args);
}
};
return es.map(function (_, callback) {
console.log('defer');
if (handle !== undefined) {
clearTimeout(handle);
}
handle = setTimeout(() => {
handle = undefined;
const previous = pending;
pending = [];
fn()
.on('error', sendAll('error'))
.on('data', sendAll('data'))
.on('end', sendAll('end'));
}, duration);
pending.push(this);
});
};
const compileFromSources = (callback) => {
const proc = cp.spawn('cargo', ['--color', 'always', 'build'], {
cwd: root,
stdio: ['ignore', 'pipe', 'pipe'],
env: existsSync(platformOpensslDir) ? { OPENSSL_DIR: platformOpensslDir, ...process.env } : process.env
});
/** @type Buffer[] */
const stdoutErr = [];
proc.stdout.on('data', d => stdoutErr.push(d));
proc.stderr.on('data', d => stdoutErr.push(d));
proc.on('error', callback);
proc.on('exit', code => {
if (code !== 0) {
callback(Buffer.concat(stdoutErr).toString());
} else {
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 });
cp.spawnSync(
process.platform === 'win32' ? 'npm.cmd' : 'npm',
['pack', '@vscode/openssl-prebuilt'],
{ stdio: ['ignore', 'ignore', 'inherit'], cwd: dir }
);
gulp.src('*.tgz', { cwd: dir })
.pipe(gunzip())
.pipe(untar())
.pipe(gulp.dest(`${root}/openssl`))
.on('error', callback)
.on('end', () => {
rmSync(dir, { recursive: true, force: true });
callback();
});
};
const compileWithOpenSSLCheck = (/** @type import('./lib/reporter').IReporter */ reporter) => es.map((_, callback) => {
compileFromSources(err => {
if (!err) {
// no-op
} else if (err.toString().includes('Could not find directory of OpenSSL installation') && !existsSync(platformOpensslDir)) {
fancyLog(ansiColors.yellow(`[cli]`), 'OpenSSL libraries not found, acquiring prebuilt bits...');
acquireBuiltOpenSSL(err => {
if (err) {
callback(err);
} else {
compileFromSources(err => {
if (err) {
reporter(err.toString());
}
callback(null, '');
});
}
});
} else {
reporter(err.toString());
}
callback(null, '');
});
});
const warnIfRustNotInstalled = () => {
if (!hasLocalRust()) {
fancyLog(ansiColors.yellow(`[cli]`), 'No local Rust install detected, compilation may fail.');
fancyLog(ansiColors.yellow(`[cli]`), 'Get rust from: https://rustup.rs/');
}
};
const compileCliTask = task.define('compile-cli', () => {
warnIfRustNotInstalled();
const reporter = createReporter('cli');
return gulp.src(`${root}/Cargo.toml`)
.pipe(compileWithOpenSSLCheck(reporter))
.pipe(reporter.end(true));
});
const watchCliTask = task.define('watch-cli', () => {
warnIfRustNotInstalled();
return watcher(`${src}/**`, { read: false })
.pipe(debounce(compileCliTask));
});
gulp.task(compileCliTask);
gulp.task(watchCliTask);
================================================
FILE: build/gulpfile.compile.js
================================================
/*---------------------------------------------------------------------------------------------
* 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');
/**
* @param {boolean} disableMangle
*/
function makeCompileBuildTask(disableMangle) {
return task.series(
util.rimraf('out-build'),
date.writeISODate('out-build'),
compilation.compileApiProposalNamesTask,
compilation.compileTask('src', 'out-build', true, { disableMangle })
);
}
// Local/PR compile, including nls and inline sources in sourcemaps, minification, no mangling
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));
gulp.task(compileBuildWithManglingTask);
exports.compileBuildWithManglingTask = compileBuildWithManglingTask;
================================================
FILE: build/gulpfile.editor.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 root = path.dirname(__dirname);
const sha1 = getVersion(root);
const semver = require('./monaco/package.json').version;
const headerVersion = semver + '(' + sha1 + ')';
const BUNDLED_FILE_HEADER = [
'/*!-----------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Version: ' + headerVersion,
' * Released under the MIT license',
' * https://github.com/microsoft/vscode/blob/main/LICENSE.txt',
' *-----------------------------------------------------------*/',
''
].join('\n');
const extractEditorSrcTask = task.define('extract-editor-src', () => {
const apiusages = monacoapi.execute().usageContent;
const extrausages = fs.readFileSync(path.join(root, 'build', 'monaco', 'monaco.usage.recipe')).toString();
standalone.extractEditor({
sourcesRoot: path.join(root, 'src'),
entryPoints: [
'vs/editor/editor.main',
'vs/editor/editor.worker.start',
'vs/editor/common/services/editorWebWorkerMain',
],
inlineEntryPoints: [
apiusages,
extrausages
],
typings: [],
shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers
importIgnorePattern: /\.css$/,
destRoot: path.join(root, 'out-editor-src'),
tsOutDir: '../out-monaco-editor-core/esm/vs',
redirects: {
'@vscode/tree-sitter-wasm': '../node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter',
}
});
});
const compileEditorESMTask = task.define('compile-editor-esm', () => {
const src = 'out-editor-src';
const out = 'out-monaco-editor-core/esm';
const compile = compilation.createCompile(src, { build: true, emitError: true, transpileOnly: false, preserveEnglish: true });
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
return (
srcPipe
.pipe(compile())
.pipe(i18n.processNlsFiles({
out,
fileHeader: BUNDLED_FILE_HEADER,
languages: i18n.defaultLanguages,
}))
.pipe(filter(['**', '!**/inlineEntryPoint*', '!**/tsconfig.json', '!**/loader.js']))
.pipe(gulp.dest(out))
);
});
/**
* @param {string} contents
*/
function toExternalDTS(contents) {
const lines = contents.split(/\r\n|\r|\n/);
let killNextCloseCurlyBrace = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (killNextCloseCurlyBrace) {
if ('}' === line) {
lines[i] = '';
killNextCloseCurlyBrace = false;
continue;
}
if (line.indexOf(' ') === 0) {
lines[i] = line.substr(4);
} else if (line.charAt(0) === '\t') {
lines[i] = line.substr(1);
}
continue;
}
if ('declare namespace monaco {' === line) {
lines[i] = '';
killNextCloseCurlyBrace = true;
continue;
}
if (line.indexOf('declare namespace monaco.') === 0) {
lines[i] = line.replace('declare namespace monaco.', 'export namespace ');
}
if (line.indexOf('declare let MonacoEnvironment') === 0) {
lines[i] = `declare global {\n let MonacoEnvironment: Environment | undefined;\n}`;
}
if (line.indexOf('\tMonacoEnvironment?') === 0) {
lines[i] = ` MonacoEnvironment?: Environment | undefined;`;
}
}
return lines.join('\n').replace(/\n\n\n+/g, '\n\n');
}
const finalEditorResourcesTask = task.define('final-editor-resources', () => {
return es.merge(
// other assets
es.merge(
gulp.src('build/monaco/LICENSE'),
gulp.src('build/monaco/ThirdPartyNotices.txt'),
gulp.src('src/vs/monaco.d.ts')
).pipe(gulp.dest('out-monaco-editor-core')),
// place the .d.ts in the esm folder
gulp.src('src/vs/monaco.d.ts')
.pipe(es.through(function (data) {
this.emit('data', new File({
path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'),
base: data.base,
contents: Buffer.from(toExternalDTS(data.contents.toString()))
}));
}))
.pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')),
// package.json
gulp.src('build/monaco/package.json')
.pipe(es.through(function (data) {
const json = JSON.parse(data.contents.toString());
json.private = false;
data.contents = Buffer.from(JSON.stringify(json, null, ' '));
this.emit('data', data);
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// version.txt
gulp.src('build/monaco/version.txt')
.pipe(es.through(function (data) {
data.contents = Buffer.from(`monaco-editor-core: https://github.com/microsoft/vscode/tree/${sha1}`);
this.emit('data', data);
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// README.md
gulp.src('build/monaco/README-npm.md')
.pipe(es.through(function (data) {
this.emit('data', new File({
path: data.path.replace(/README-npm\.md/, 'README.md'),
base: data.base,
contents: data.contents
}));
}))
.pipe(gulp.dest('out-monaco-editor-core')),
);
});
gulp.task('extract-editor-src',
task.series(
util.rimraf('out-editor-src'),
extractEditorSrcTask
)
);
gulp.task('editor-distro',
task.series(
task.parallel(
util.rimraf('out-editor-src'),
util.rimraf('out-monaco-editor-core'),
),
extractEditorSrcTask,
compileEditorESMTask,
finalEditorResourcesTask
)
);
gulp.task('monacodts', task.define('monacodts', () => {
const result = monacoapi.execute();
fs.writeFileSync(result.filePath, result.content);
fs.writeFileSync(path.join(root, 'src/vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
return Promise.resolve(true);
}));
//#region monaco type checking
/**
* @param {boolean} watch
*/
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) {
args.push('-w');
}
const child = cp.spawn(`node`, args, {
cwd: path.join(__dirname, '..'),
// stdio: [null, 'pipe', 'inherit']
});
const errors = [];
const reporter = createReporter('monaco');
/** @type {NodeJS.ReadWriteStream | undefined} */
let report;
const magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
child.stdout.on('data', data => {
let str = String(data);
str = str.replace(magic, '').trim();
if (str.indexOf('Starting compilation') >= 0 || str.indexOf('File change detected') >= 0) {
errors.length = 0;
report = reporter.end(false);
} else if (str.indexOf('Compilation complete') >= 0) {
// @ts-ignore
report.end();
} else if (str) {
const match = /(.*\(\d+,\d+\): )(.*: )(.*)/.exec(str);
if (match) {
// trying to massage the message so that it matches the gulp-tsb error messages
// e.g. src/vs/base/common/strings.ts(663,5): error TS2322: Type '1234' is not assignable to type 'string'.
const fullpath = path.join(root, match[1]);
const message = match[3];
reporter(fullpath + message);
} else {
reporter(str);
}
}
});
child.on('exit', resolve);
child.on('error', reject);
});
};
}
const monacoTypecheckWatchTask = task.define('monaco-typecheck-watch', createTscCompileTask(true));
exports.monacoTypecheckWatchTask = monacoTypecheckWatchTask;
const monacoTypecheckTask = task.define('monaco-typecheck', createTscCompileTask(false));
exports.monacoTypecheckTask = monacoTypecheckTask;
//#endregion
================================================
FILE: build/gulpfile.extensions.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Increase max listeners for event emitters
require('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');
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', {
// cwd: extensionsPath,
// ignore: ['**/out/**', '**/node_modules/**']
// });
const compilations = [
'extensions/configuration-editing/tsconfig.json',
'extensions/css-language-features/client/tsconfig.json',
'extensions/css-language-features/server/tsconfig.json',
'extensions/debug-auto-launch/tsconfig.json',
'extensions/debug-server-ready/tsconfig.json',
'extensions/emmet/tsconfig.json',
'extensions/extension-editing/tsconfig.json',
'extensions/git/tsconfig.json',
'extensions/git-base/tsconfig.json',
'extensions/github/tsconfig.json',
'extensions/github-authentication/tsconfig.json',
'extensions/grunt/tsconfig.json',
'extensions/gulp/tsconfig.json',
'extensions/html-language-features/client/tsconfig.json',
'extensions/html-language-features/server/tsconfig.json',
'extensions/ipynb/tsconfig.json',
'extensions/jake/tsconfig.json',
'extensions/json-language-features/client/tsconfig.json',
'extensions/json-language-features/server/tsconfig.json',
'extensions/markdown-language-features/preview-src/tsconfig.json',
'extensions/markdown-language-features/tsconfig.json',
'extensions/markdown-math/tsconfig.json',
'extensions/media-preview/tsconfig.json',
'extensions/merge-conflict/tsconfig.json',
'extensions/terminal-suggest/tsconfig.json',
'extensions/microsoft-authentication/tsconfig.json',
'extensions/notebook-renderers/tsconfig.json',
'extensions/npm/tsconfig.json',
'extensions/php-language-features/tsconfig.json',
'extensions/references-view/tsconfig.json',
'extensions/search-result/tsconfig.json',
'extensions/simple-browser/tsconfig.json',
'extensions/tunnel-forwarding/tsconfig.json',
'extensions/typescript-language-features/test-workspace/tsconfig.json',
'extensions/typescript-language-features/web/tsconfig.json',
'extensions/typescript-language-features/tsconfig.json',
'extensions/vscode-api-tests/tsconfig.json',
'extensions/vscode-colorize-tests/tsconfig.json',
'extensions/vscode-colorize-perf-tests/tsconfig.json',
'extensions/vscode-test-resolver/tsconfig.json',
'.vscode/extensions/vscode-selfhost-test-provider/tsconfig.json',
'.vscode/extensions/vscode-selfhost-import-aid/tsconfig.json',
];
const getBaseUrl = out => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`;
const tasks = compilations.map(function (tsconfigFile) {
const absolutePath = path.join(root, tsconfigFile);
const relativeDirname = path.dirname(tsconfigFile.replace(/^(.*\/)?extensions\//i, ''));
const overrideOptions = {};
overrideOptions.sourceMap = true;
const name = relativeDirname.replace(/\//g, '-');
const srcRoot = path.dirname(tsconfigFile);
const srcBase = path.join(srcRoot, 'src');
const src = path.join(srcBase, '**');
const srcOpts = { cwd: root, base: srcBase, dot: true };
const out = path.join(srcRoot, 'out');
const baseUrl = getBaseUrl(out);
let headerId, headerOut;
const index = relativeDirname.indexOf('/');
if (index < 0) {
headerId = 'vscode.' + relativeDirname;
headerOut = 'out';
} else {
headerId = 'vscode.' + relativeDirname.substr(0, index);
headerOut = relativeDirname.substr(index + 1) + '/out';
}
function createPipeline(build, emitError, transpileOnly) {
const tsb = require('./lib/tsb');
const sourcemaps = require('gulp-sourcemaps');
const reporter = createReporter('extensions');
overrideOptions.inlineSources = Boolean(build);
overrideOptions.base = path.dirname(absolutePath);
const compilation = tsb.create(absolutePath, overrideOptions, { verbose: false, transpileOnly, transpileOnlyIncludesDts: transpileOnly, transpileWithSwc: true }, err => reporter(err.toString()));
const pipeline = function () {
const input = es.through();
const tsFilter = filter(['**/*.ts', '!**/lib/lib*.d.ts', '!**/node_modules/**'], { restore: true, dot: true });
const output = input
.pipe(plumber({
errorHandler: function (err) {
if (err && !err.__reporter__) {
reporter(err);
}
}
}))
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(compilation())
.pipe(build ? util.stripSourceMappingURL() : es.through())
.pipe(sourcemaps.write('.', {
sourceMappingURL: !build ? null : f => `${baseUrl}/${f.relative}.map`,
addComment: !!build,
includeContent: !!build,
// note: trailing slash is important, else the source URLs in V8's file coverage are incorrect
sourceRoot: '../src/',
}))
.pipe(tsFilter.restore)
.pipe(reporter.end(emitError));
return es.duplex(input, output);
};
// add src-stream for project files
pipeline.tsProjectSrc = () => {
return compilation.src(srcOpts);
};
return pipeline;
}
const cleanTask = task.define(`clean-extension-${name}`, util.rimraf(out));
const transpileTask = task.define(`transpile-extension:${name}`, task.series(cleanTask, () => {
const pipeline = createPipeline(false, 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));
}));
const compileTask = task.define(`compile-extension:${name}`, task.series(cleanTask, () => {
const pipeline = createPipeline(false, 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));
}));
const watchTask = task.define(`watch-extension:${name}`, task.series(cleanTask, () => {
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 } });
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 };
});
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)));
gulp.task(compileExtensionsTask);
exports.compileExtensionsTask = compileExtensionsTask;
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));
gulp.task(compileExtensionMediaTask);
exports.compileExtensionMediaTask = compileExtensionMediaTask;
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'));
gulp.task(compileExtensionMediaBuildTask);
exports.compileExtensionMediaBuildTask = compileExtensionMediaBuildTask;
//#endregion
//#region Azure Pipelines
/**
* Cleans the build directory for extensions
*/
const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions'));
exports.cleanExtensionsBuildTask = cleanExtensionsBuildTask;
/**
* brings in the marketplace extensions for the build
*/
const bundleMarketplaceExtensionsBuildTask = task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream(false).pipe(gulp.dest('.build')));
/**
* 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(
bundleMarketplaceExtensionsBuildTask,
task.define('bundle-non-native-extensions-build', () => ext.packageNonNativeLocalExtensionsStream().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().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(
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.
gulp.task(task.define('extensions-ci', task.series(compileNonNativeExtensionsBuildTask, compileExtensionMediaBuildTask)));
const compileExtensionsBuildPullRequestTask = task.define('compile-extensions-build-pr', task.series(
cleanExtensionsBuildTask,
bundleMarketplaceExtensionsBuildTask,
task.define('bundle-extensions-build-pr', () => ext.packageAllLocalExtensionsStream(false, true).pipe(gulp.dest('.build'))),
));
gulp.task(compileExtensionsBuildPullRequestTask);
// This task is run in the compilation stage of the PR pipeline. We compile all extensions in it to verify compilation.
gulp.task(task.define('extensions-ci-pr', task.series(compileExtensionsBuildPullRequestTask, compileExtensionMediaBuildTask)));
//#endregion
const compileWebExtensionsTask = task.define('compile-web', () => buildWebExtensions(false));
gulp.task(compileWebExtensionsTask);
exports.compileWebExtensionsTask = compileWebExtensionsTask;
const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true));
gulp.task(watchWebExtensionsTask);
exports.watchWebExtensionsTask = watchWebExtensionsTask;
/**
* @param {boolean} isWatch
*/
async function buildWebExtensions(isWatch) {
const extensionsPath = path.join(root, 'extensions');
const webpackConfigLocations = await nodeUtil.promisify(glob)(
path.join(extensionsPath, '**', 'extension-browser.webpack.config.js'),
{ ignore: ['**/node_modules'] }
);
return ext.webpackExtensions('packaging web extension', isWatch, webpackConfigLocations.map(configPath => ({ configPath })));
}
================================================
FILE: build/gulpfile.hygiene.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const gulp = require('gulp');
const es = require('event-stream');
const path = require('path');
const task = require('./lib/task');
const { hygiene } = require('./hygiene');
/**
* @param {string} actualPath
*/
function checkPackageJSON(actualPath) {
const actual = require(path.join(__dirname, '..', actualPath));
const rootPackageJSON = require('../package.json');
const checkIncluded = (set1, set2) => {
for (const depName in set1) {
const depVersion = set1[depName];
const rootDepVersion = set2[depName];
if (!rootDepVersion) {
// missing in root is allowed
continue;
}
if (depVersion !== rootDepVersion) {
this.emit(
'error',
`The dependency ${depName} in '${actualPath}' (${depVersion}) is different than in the root package.json (${rootDepVersion})`
);
}
}
};
checkIncluded(actual.dependencies, rootPackageJSON.dependencies);
checkIncluded(actual.devDependencies, rootPackageJSON.devDependencies);
}
const checkPackageJSONTask = task.define('check-package-json', () => {
return gulp.src('package.json').pipe(
es.through(function () {
checkPackageJSON.call(this, 'remote/package.json');
checkPackageJSON.call(this, 'remote/web/package.json');
checkPackageJSON.call(this, 'build/package.json');
})
);
});
gulp.task(checkPackageJSONTask);
const hygieneTask = task.define('hygiene', task.series(checkPackageJSONTask, () => hygiene(undefined, false)));
gulp.task(hygieneTask);
================================================
FILE: build/gulpfile.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
// Increase max listeners for event emitters
require('events').EventEmitter.defaultMaxListeners = 100;
const gulp = require('gulp');
const util = require('./lib/util');
const task = require('./lib/task');
const { transpileClientSWC, transpileTask, compileTask, watchTask, compileApiProposalNamesTask, watchApiProposalNamesTask } = require('./lib/compilation');
const { monacoTypecheckTask/* , monacoTypecheckWatchTask */ } = require('./gulpfile.editor');
const { compileExtensionsTask, watchExtensionsTask, compileExtensionMediaTask } = require('./gulpfile.extensions');
// API proposal names
gulp.task(compileApiProposalNamesTask);
gulp.task(watchApiProposalNamesTask);
// SWC Client Transpile
const transpileClientSWCTask = task.define('transpile-client-esbuild', task.series(util.rimraf('out'), transpileTask('src', 'out', true)));
gulp.task(transpileClientSWCTask);
// Transpile only
const transpileClientTask = task.define('transpile-client', task.series(util.rimraf('out'), transpileTask('src', 'out')));
gulp.task(transpileClientTask);
// Fast compile for development time
const compileClientTask = task.define('compile-client', task.series(util.rimraf('out'), compileApiProposalNamesTask, compileTask('src', 'out', false)));
gulp.task(compileClientTask);
const watchClientTask = task.define('watch-client', task.series(util.rimraf('out'), task.parallel(watchTask('out', false), watchApiProposalNamesTask)));
gulp.task(watchClientTask);
// All
const _compileTask = task.define('compile', task.parallel(monacoTypecheckTask, compileClientTask, compileExtensionsTask, compileExtensionMediaTask));
gulp.task(_compileTask);
gulp.task(task.define('watch', task.parallel(/* monacoTypecheckWatchTask, */ watchClientTask, watchExtensionsTask)));
// Default
gulp.task('default', _compileTask);
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
process.exit(1);
});
// Load all the gulpfiles only if running tasks other than the editor tasks
require('glob').sync('gulpfile.*.js', { cwd: __dirname })
.forEach(f => require(`./${f}`));
================================================
FILE: build/gulpfile.reh.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 REPO_ROOT = path.dirname(__dirname);
const commit = getVersion(REPO_ROOT);
const BUILD_ROOT = path.dirname(REPO_ROOT);
const REMOTE_FOLDER = path.join(REPO_ROOT, 'remote');
// Targets
const BUILD_TARGETS = [
{ platform: 'win32', arch: 'x64' },
{ platform: 'win32', arch: 'arm64' },
{ platform: 'darwin', arch: 'x64' },
{ platform: 'darwin', arch: 'arm64' },
{ platform: 'linux', arch: 'x64' },
{ platform: 'linux', arch: 'armhf' },
{ platform: 'linux', arch: 'arm64' },
{ platform: 'alpine', arch: 'arm64' },
// legacy: we use to ship only one alpine so it was put in the arch, but now we ship
// multiple alpine images and moved to a better model (alpine as the platform)
{ platform: 'linux', arch: 'alpine' },
];
const serverResourceIncludes = [
// NLS
'out-build/nls.messages.json',
// Process monitor
'out-build/vs/base/node/cpuUsage.sh',
'out-build/vs/base/node/ps.sh',
// External Terminal
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
// Terminal shell integration
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration.ps1',
'out-build/vs/workbench/contrib/terminal/common/scripts/CodeTabExpansion.psm1',
'out-build/vs/workbench/contrib/terminal/common/scripts/GitTabExpansion.psm1',
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration-bash.sh',
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration-env.zsh',
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration-profile.zsh',
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh',
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration-login.zsh',
'out-build/vs/workbench/contrib/terminal/common/scripts/shellIntegration.fish',
];
const serverResourceExcludes = [
'!out-build/vs/**/{electron-sandbox,electron-main,electron-utility}/**',
'!out-build/vs/editor/standalone/**',
'!out-build/vs/workbench/**/*-tb.png',
'!**/test/**'
];
const serverResources = [
...serverResourceIncludes,
...serverResourceExcludes
];
const serverWithWebResourceIncludes = [
...serverResourceIncludes,
'out-build/vs/code/browser/workbench/*.html',
...vscodeWebResourceIncludes
];
const serverWithWebResourceExcludes = [
...serverResourceExcludes,
'!out-build/vs/code/**/*-dev.html'
];
const serverWithWebResources = [
...serverWithWebResourceIncludes,
...serverWithWebResourceExcludes
];
const serverEntryPoints = buildfile.codeServer;
const webEntryPoints = [
buildfile.workerEditor,
buildfile.workerExtensionHost,
buildfile.workerNotebook,
buildfile.workerLanguageDetection,
buildfile.workerLocalFileSearch,
buildfile.workerOutputLinks,
buildfile.workerBackgroundTokenization,
buildfile.keyboardMaps,
buildfile.codeWeb
].flat();
const serverWithWebEntryPoints = [
// Include all of server
...serverEntryPoints,
// Include all of web
...webEntryPoints,
].flat();
const bootstrapEntryPoints = [
'out-build/server-main.js',
'out-build/server-cli.js',
'out-build/bootstrap-fork.js'
];
function getNodeVersion() {
const npmrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.npmrc'), 'utf8');
const nodeVersion = /^target="(.*)"$/m.exec(npmrc)[1];
const internalNodeVersion = /^ms_build_id="(.*)"$/m.exec(npmrc)[1];
return { nodeVersion, internalNodeVersion };
}
function getNodeChecksum(expectedName) {
const nodeJsChecksums = fs.readFileSync(path.join(REPO_ROOT, 'build', 'checksums', 'nodejs.txt'), 'utf8');
for (const line of nodeJsChecksums.split('\n')) {
const [checksum, name] = line.split(/\s+/);
if (name === expectedName) {
return checksum;
}
}
return undefined;
}
function extractAlpinefromDocker(nodeVersion, platform, arch) {
const imageName = arch === 'arm64' ? 'arm64v8/node' : 'node';
log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from docker image ${imageName}`);
const contents = cp.execSync(`docker run --rm ${imageName}:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' });
return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } })]);
}
const { nodeVersion, internalNodeVersion } = getNodeVersion();
BUILD_TARGETS.forEach(({ platform, arch }) => {
gulp.task(task.define(`node-${platform}-${arch}`, () => {
const nodePath = path.join('.build', 'node', `v${nodeVersion}`, `${platform}-${arch}`);
if (!fs.existsSync(nodePath)) {
util.rimraf(nodePath);
return nodejs(platform, arch)
.pipe(vfs.dest(nodePath));
}
return Promise.resolve(null);
}));
});
const defaultNodeTask = gulp.task(`node-${process.platform}-${process.arch}`);
if (defaultNodeTask) {
gulp.task(task.define('node', defaultNodeTask));
}
function nodejs(platform, arch) {
const { fetchUrls, fetchGithub } = require('./lib/fetch');
const untar = require('gulp-untar');
if (arch === 'armhf') {
arch = 'armv7l';
} else if (arch === 'alpine') {
platform = 'alpine';
arch = 'x64';
}
log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejsRepository}...`);
const glibcPrefix = process.env['VSCODE_NODE_GLIBC'] ?? '';
let expectedName;
switch (platform) {
case 'win32':
expectedName = product.nodejsRepository !== 'https://nodejs.org' ?
`win-${arch}-node.exe` : `win-${arch}/node.exe`;
break;
case 'darwin':
expectedName = `node-v${nodeVersion}-${platform}-${arch}.tar.gz`;
break;
case 'linux':
expectedName = `node-v${nodeVersion}${glibcPrefix}-${platform}-${arch}.tar.gz`;
break;
case 'alpine':
expectedName = `node-v${nodeVersion}-linux-${arch}-musl.tar.gz`;
break;
}
const checksumSha256 = getNodeChecksum(expectedName);
if (checksumSha256) {
log(`Using SHA256 checksum for checking integrity: ${checksumSha256}`);
} else {
log.warn(`Unable to verify integrity of downloaded node.js binary because no SHA256 checksum was found!`);
}
switch (platform) {
case 'win32':
return (product.nodejsRepository !== 'https://nodejs.org' ?
fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) :
fetchUrls(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org', checksumSha256 }))
.pipe(rename('node.exe'));
case 'darwin':
case 'linux':
return (product.nodejsRepository !== 'https://nodejs.org' ?
fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) :
fetchUrls(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org', checksumSha256 })
).pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar())))
.pipe(filter('**/node'))
.pipe(util.setExecutableBit('**'))
.pipe(rename('node'));
case 'alpine':
return product.nodejsRepository !== 'https://nodejs.org' ?
fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 })
.pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar())))
.pipe(filter('**/node'))
.pipe(util.setExecutableBit('**'))
.pipe(rename('node'))
: extractAlpinefromDocker(nodeVersion, platform, arch);
}
}
function packageTask(type, platform, arch, 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'); }))
.pipe(util.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', '!**/*.js.map']));
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
const isUIExtension = (manifest) => {
switch (manifest.extensionKind) {
case 'ui': return true;
case 'workspace': return false;
default: {
if (manifest.main) {
return false;
}
if (manifest.contributes && Object.keys(manifest.contributes).some(key => workspaceExtensionPoints.indexOf(key) !== -1)) {
return false;
}
// Default is UI Extension
return true;
}
}
};
const localWorkspaceExtensions = glob.sync('extensions/*/package.json')
.filter((extensionPath) => {
if (type === 'reh-web') {
return true; // web: ship all extensions for now
}
// Skip shipping UI extensions because the client side will have them anyways
// and they'd just increase the download without being used
const manifest = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, extensionPath)).toString());
return !isUIExtension(manifest);
}).map((extensionPath) => path.basename(path.dirname(extensionPath)))
.filter(name => name !== 'vscode-api-tests' && name !== 'vscode-test-resolver'); // Do not ship the test extensions
const marketplaceExtensions = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'product.json'), 'utf8')).builtInExtensions
.filter(entry => !entry.platforms || new Set(entry.platforms).has(platform))
.filter(entry => !entry.clientOnly)
.map(entry => entry.name);
const extensionPaths = [...localWorkspaceExtensions, ...marketplaceExtensions]
.map(name => `.build/extensions/${name}/**`);
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true });
const sources = es.merge(src, extensions, extensionsCommonDependencies)
.pipe(filter(['**', '!**/*.js.map'], { dot: true }));
let version = packageJson.version;
const quality = product.quality;
if (quality && quality !== 'stable') {
version += '-' + quality;
}
const name = product.nameShort;
let packageJsonContents;
const packageJsonStream = gulp.src(['remote/package.json'], { base: 'remote' })
.pipe(json({ name, version, dependencies: undefined, optionalDependencies: undefined, type: 'module' }))
.pipe(es.through(function (file) {
packageJsonContents = file.contents.toString();
this.emit('data', file);
}));
let productJsonContents;
const productJsonStream = gulp.src(['product.json'], { base: '.' })
.pipe(json({ commit, date: readISODate('out-build'), version }))
.pipe(es.through(function (file) {
productJsonContents = file.contents.toString();
this.emit('data', file);
}));
const license = gulp.src(['remote/LICENSE'], { base: 'remote', allowEmpty: true });
const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path));
const productionDependencies = getProductionDependencies(REMOTE_FOLDER);
const dependenciesSrc = productionDependencies.map(d => path.relative(REPO_ROOT, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`, `!${d}/.bin/**`]).flat();
const deps = gulp.src(dependenciesSrc, { base: 'remote', dot: true })
// filter out unnecessary files, no source maps in server build
.pipe(filter(['**', '!**/package-lock.json', '!**/*.js.map']))
.pipe(util.cleanNodeModules(path.join(__dirname, '.moduleignore')))
.pipe(util.cleanNodeModules(path.join(__dirname, `.moduleignore.${process.platform}`)))
.pipe(jsFilter)
.pipe(util.stripSourceMappingURL())
.pipe(jsFilter.restore);
const nodePath = `.build/node/v${nodeVersion}/${platform}-${arch}`;
const node = gulp.src(`${nodePath}/**`, { base: nodePath, dot: true });
let web = [];
if (type === 'reh-web') {
web = [
'resources/server/favicon.ico',
'resources/server/code-192.png',
'resources/server/code-512.png',
'resources/server/manifest.json'
].map(resource => gulp.src(resource, { base: '.' }).pipe(rename(resource)));
}
const all = es.merge(
packageJsonStream,
productJsonStream,
license,
sources,
deps,
node,
...web
);
let result = all
.pipe(util.skipDirectories())
.pipe(util.fixWin32DirectoryPermissions());
if (platform === 'win32') {
result = es.merge(result,
gulp.src('resources/server/bin/remote-cli/code.cmd', { base: '.' })
.pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/remote-cli/${product.applicationName}.cmd`)),
gulp.src('resources/server/bin/helpers/browser.cmd', { base: '.' })
.pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/helpers/browser.cmd`)),
gulp.src('resources/server/bin/code-server.cmd', { base: '.' })
.pipe(rename(`bin/${product.serverApplicationName}.cmd`)),
);
} else if (platform === 'linux' || platform === 'alpine' || platform === 'darwin') {
result = es.merge(result,
gulp.src(`resources/server/bin/remote-cli/${platform === 'darwin' ? 'code-darwin.sh' : 'code-linux.sh'}`, { base: '.' })
.pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/remote-cli/${product.applicationName}`))
.pipe(util.setExecutableBit()),
gulp.src(`resources/server/bin/helpers/${platform === 'darwin' ? 'browser-darwin.sh' : 'browser-linux.sh'}`, { base: '.' })
.pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(`bin/helpers/browser.sh`))
.pipe(util.setExecutableBit()),
gulp.src(`resources/server/bin/${platform === 'darwin' ? 'code-server-darwin.sh' : 'code-server-linux.sh'}`, { base: '.' })
.pipe(rename(`bin/${product.serverApplicationName}`))
.pipe(util.setExecutableBit())
);
}
if (platform === 'linux' || platform === 'alpine') {
result = es.merge(result,
gulp.src(`resources/server/bin/helpers/check-requirements-linux.sh`, { base: '.' })
.pipe(rename(`bin/helpers/check-requirements.sh`))
.pipe(util.setExecutableBit())
);
}
result = inlineMeta(result, {
targetPaths: bootstrapEntryPoints,
packageJsonFn: () => packageJsonContents,
productJsonFn: () => productJsonContents
});
return result.pipe(vfs.dest(destination));
};
}
/**
* @param {object} product The parsed product.json file contents
*/
function tweakProductForServerWeb(product) {
const result = { ...product };
delete result.webEndpointUrlTemplate;
return result;
}
['reh', 'reh-web'].forEach(type => {
const bundleTask = task.define(`bundle-vscode-${type}`, task.series(
util.rimraf(`out-vscode-${type}`),
optimize.bundleTask(
{
out: `out-vscode-${type}`,
esm: {
src: 'out-build',
entryPoints: [
...(type === 'reh' ? serverEntryPoints : serverWithWebEntryPoints),
...bootstrapEntryPoints
],
resources: type === 'reh' ? serverResources : serverWithWebResources,
fileContentMapper: createVSCodeWebFileContentMapper('.build/extensions', type === 'reh-web' ? tweakProductForServerWeb(product) : product)
}
}
)
));
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
bundleTask,
util.rimraf(`out-vscode-${type}-min`),
optimize.minifyTask(`out-vscode-${type}`, `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
));
gulp.task(minifyTask);
BUILD_TARGETS.forEach(buildTarget => {
const dashed = (str) => (str ? `-${str}` : ``);
const platform = buildTarget.platform;
const arch = buildTarget.arch;
['', 'min'].forEach(minified => {
const sourceFolderName = `out-vscode-${type}${dashed(minified)}`;
const destinationFolderName = `vscode-${type}${dashed(platform)}${dashed(arch)}`;
const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series(
compileNativeExtensionsBuildTask,
gulp.task(`node-${platform}-${arch}`),
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
packageTask(type, platform, arch, sourceFolderName, destinationFolderName)
));
gulp.task(serverTaskCI);
const serverTask = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}`, task.series(
compileBuildWithManglingTask,
cleanExtensionsBuildTask,
compileNonNativeExtensionsBuildTask,
compileExtensionMediaBuildTask,
minified ? minifyTask : bundleTask,
serverTaskCI
));
gulp.task(serverTask);
});
});
});
================================================
FILE: build/gulpfile.scan.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 root = path.dirname(__dirname);
const BUILD_TARGETS = [
{ platform: 'win32', arch: 'x64' },
{ platform: 'win32', arch: 'arm64' },
{ platform: 'darwin', arch: null, opts: { stats: true } },
{ platform: 'linux', arch: 'x64' },
{ platform: 'linux', arch: 'armhf' },
{ platform: 'linux', arch: 'arm64' },
];
// The following files do not have PDBs downloaded for them during the download symbols process.
const excludedCheckList = ['d3dcompiler_47.dll'];
BUILD_TARGETS.forEach(buildTarget => {
const dashed = (/** @type {string | null} */ str) => (str ? `-${str}` : ``);
const platform = buildTarget.platform;
const arch = buildTarget.arch;
const destinationExe = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'bin');
const destinationPdb = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'pdb');
const tasks = [];
// removal tasks
tasks.push(util.rimraf(destinationExe), util.rimraf(destinationPdb));
// electron
tasks.push(() => electron.dest(destinationExe, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch }));
// pdbs for windows
if (platform === 'win32') {
tasks.push(
() => electron.dest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, pdbs: true }),
() => confirmPdbsExist(destinationExe, destinationPdb)
);
}
if (platform === 'linux') {
tasks.push(
() => electron.dest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, symbols: true })
);
}
// node modules
tasks.push(
nodeModules(destinationExe, destinationPdb, platform)
);
const setupSymbolsTask = task.define(`vscode-symbols${dashed(platform)}${dashed(arch)}`,
task.series(...tasks)
);
gulp.task(setupSymbolsTask);
});
function getProductionDependencySources() {
const productionDependencies = deps.getProductionDependencies(root);
return productionDependencies.map(d => path.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat();
}
function nodeModules(destinationExe, destinationPdb, platform) {
const exe = () => {
return gulp.src(getProductionDependencySources(), { base: '.', dot: true })
.pipe(filter([
'**/*.node',
// Exclude these paths.
// We don't build the prebuilt node files so we don't scan them
'!**/prebuilds/**/*.node',
// These are 3rd party modules that we should ignore
'!**/@parcel/watcher/**/*']))
.pipe(gulp.dest(destinationExe));
};
if (platform === 'win32') {
const pdb = () => {
return gulp.src(getProductionDependencySources(), { base: '.', dot: true })
.pipe(filter(['**/*.pdb']))
.pipe(gulp.dest(destinationPdb));
};
return gulp.parallel(exe, pdb);
}
if (platform === 'linux') {
const pdb = () => {
return gulp.src(getProductionDependencySources(), { base: '.', dot: true })
.pipe(filter(['**/*.sym']))
.pipe(gulp.dest(destinationPdb));
};
return gulp.parallel(exe, pdb);
}
return exe;
}
function confirmPdbsExist(destinationExe, destinationPdb) {
readdirSync(destinationExe).forEach(file => {
if (excludedCheckList.includes(file)) {
return;
}
if (file.endsWith('.dll') || file.endsWith('.exe')) {
const pdb = `${file}.pdb`;
if (!existsSync(path.join(destinationPdb, pdb))) {
throw new Error(`Missing pdb file for ${file}. Tried searching for ${pdb} in ${destinationPdb}.`);
}
}
});
return Promise.resolve();
}
================================================
FILE: build/gulpfile.vscode.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 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 = [
buildfile.workerEditor,
buildfile.workerExtensionHost,
buildfile.workerNotebook,
buildfile.workerLanguageDetection,
buildfile.workerLocalFileSearch,
buildfile.workerProfileAnalysis,
buildfile.workerOutputLinks,
buildfile.workerBackgroundTokenization,
buildfile.workbenchDesktop,
buildfile.code
].flat();
const vscodeResourceIncludes = [
// NLS
'out-build/nls.messages.json',
'out-build/nls.keys.json',
// Workbench
'out-build/vs/code/electron-sandbox/workbench/workbench.html',
// Electron Preload
'out-build/vs/base/parts/sandbox/electron-sandbox/preload.js',
'out-build/vs/base/parts/sandbox/electron-sandbox/preload-aux.js',
// Node Scripts
'out-build/vs/base/node/{terminateProcess.sh,cpuUsage.sh,ps.sh}',
// Touchbar
'out-build/vs/workbench/browser/parts/editor/media/*.png',
'out-build/vs/workbench/contrib/debug/browser/media/*.png',
// External Terminal
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
// Terminal shell integration
'out-build/vs/workbench/contrib/terminal/common/scripts/*.fish',
'out-build/vs/workbench/contrib/terminal/common/scripts/*.ps1',
'out-build/vs/workbench/contrib/terminal/common/scripts/*.psm1',
'out-build/vs/workbench/contrib/terminal/common/scripts/*.sh',
'out-build/vs/workbench/contrib/terminal/common/scripts/*.zsh',
// Accessibility Signals
'out-build/vs/platform/accessibilitySignal/browser/media/*.mp3',
// Welcome
'out-build/vs/workbench/contrib/welcomeGettingStarted/common/media/**/*.{svg,png}',
// Extensions
'out-build/vs/workbench/contrib/extensions/browser/media/{theme-icon.png,language-icon.svg}',
'out-build/vs/workbench/services/extensionManagement/common/media/*.{svg,png}',
// Webview
'out-build/vs/workbench/contrib/webview/browser/pre/*.{js,html}',
// Extension Host Worker
'out-build/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html',
// Process Explorer
'out-build/vs/code/electron-sandbox/processExplorer/processExplorer.html',
// Tree Sitter highlights
'out-build/vs/editor/common/languages/highlights/*.scm',
// Tree Sitter injection queries
'out-build/vs/editor/common/languages/injections/*.scm',
];
const vscodeResources = [
// Includes
...vscodeResourceIncludes,
// Excludes
'!out-build/vs/code/browser/**',
'!out-build/vs/editor/standalone/**',
'!out-build/vs/code/**/*-dev.html',
'!out-build/vs/workbench/contrib/issue/**/*-dev.html',
'!**/test/**'
];
const bootstrapEntryPoints = [
'out-build/main.js',
'out-build/cli.js',
'out-build/bootstrap-fork.js'
];
const bundleVSCodeTask = task.define('bundle-vscode', task.series(
util.rimraf('out-vscode'),
// Optimize: bundles source files automatically based on
// import statements based on the passed in entry points.
// In addition, concat window related bootstrap files into
// a single file.
optimize.bundleTask(
{
out: 'out-vscode',
esm: {
src: 'out-build',
entryPoints: [
...vscodeEntryPoints,
...bootstrapEntryPoints
],
resources: vscodeResources,
fileContentMapper: filePath => {
if (
filePath.endsWith('vs/code/electron-sandbox/workbench/workbench.js') ||
filePath.endsWith('vs/code/electron-sandbox/processExplorer/processExplorer.js')) {
return async (content) => {
const bootstrapWindowContent = await fs.promises.readFile(path.join(root, 'out-build', 'bootstrap-window.js'), 'utf-8');
return `${bootstrapWindowContent}\n${content}`; // prepend bootstrap-window.js content to entry points that are Electron windows
};
}
return undefined;
},
skipTSBoilerplateRemoval: entryPoint =>
entryPoint === 'vs/code/electron-sandbox/workbench/workbench' ||
entryPoint === 'vs/code/electron-sandbox/processExplorer/processExplorer',
}
}
)
));
gulp.task(bundleVSCodeTask);
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
const minifyVSCodeTask = task.define('minify-vscode', task.series(
bundleVSCodeTask,
util.rimraf('out-vscode-min'),
optimize.minifyTask('out-vscode', `${sourceMappingURLBase}/core`)
));
gulp.task(minifyVSCodeTask);
const coreCI = task.define('core-ci', task.series(
gulp.task('compile-build-with-mangling'),
task.parallel(
gulp.task('minify-vscode'),
gulp.task('minify-vscode-reh'),
gulp.task('minify-vscode-reh-web'),
)
));
gulp.task(coreCI);
const coreCIPR = task.define('core-ci-pr', task.series(
gulp.task('compile-build-without-mangling'),
task.parallel(
gulp.task('minify-vscode'),
gulp.task('minify-vscode-reh'),
gulp.task('minify-vscode-reh-web'),
)
));
gulp.task(coreCIPR);
/**
* Compute checksums for some files.
*
* @param {string} out The out folder to read the file from.
* @param {string[]} filenames The paths to compute a checksum for.
* @return {Object} A map of paths to checksums.
*/
function computeChecksums(out, filenames) {
const result = {};
filenames.forEach(function (filename) {
const fullPath = path.join(process.cwd(), out, filename);
result[filename] = computeChecksum(fullPath);
});
return result;
}
/**
* Compute checksum for a file.
*
* @param {string} filename The absolute path to a filename.
* @return {string} The checksum for `filename`.
*/
function computeChecksum(filename) {
const contents = fs.readFileSync(filename);
const hash = crypto
.createHash('sha256')
.update(contents)
.digest('base64')
.replace(/=+$/, '');
return hash;
}
function packageTask(platform, arch, sourceFolderName, destinationFolderName, opts) {
opts = opts || {};
const destination = path.join(path.dirname(root), destinationFolderName);
platform = platform || process.platform;
return () => {
const electron = require('@vscode/gulp-electron');
const json = require('gulp-json-editor');
const out = sourceFolderName;
const checksums = computeChecksums(out, [
'vs/base/parts/sandbox/electron-sandbox/preload.js',
'vs/workbench/workbench.desktop.main.js',
'vs/workbench/workbench.desktop.main.css',
'vs/workbench/api/node/extensionHostProcess.js',
'vs/code/electron-sandbox/workbench/workbench.html',
'vs/code/electron-sandbox/workbench/workbench.js'
]);
const src = gulp.src(out + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); }))
.pipe(util.setExecutableBit(['**/*.sh']));
const platformSpecificBuiltInExtensionsExclusions = product.builtInExtensions.filter(ext => {
if (!ext.platforms) {
return false;
}
const set = new Set(ext.platforms);
return !set.has(platform);
}).map(ext => `!.build/extensions/${ext.name}/**`);
const extensions = gulp.src(['.build/extensions/**', ...platformSpecificBuiltInExtensionsExclusions], { base: '.build', dot: true });
const sources = es.merge(src, extensions)
.pipe(filter(['**', '!**/*.js.map'], { dot: true }));
let version = packageJson.version;
const quality = product.quality;
if (quality && quality !== 'stable') {
version += '-' + quality;
}
const name = product.nameShort;
const packageJsonUpdates = { name, version };
if (platform === 'linux') {
packageJsonUpdates.desktopName = `${product.applicationName}.desktop`;
}
let packageJsonContents;
const packageJsonStream = gulp.src(['package.json'], { base: '.' })
.pipe(json(packageJsonUpdates))
.pipe(es.through(function (file) {
packageJsonContents = file.contents.toString();
this.emit('data', file);
}));
let productJsonContents;
const productJsonStream = gulp.src(['product.json'], { base: '.' })
.pipe(json({ commit, date: readISODate('out-build'), checksums, version }))
.pipe(es.through(function (file) {
productJsonContents = file.contents.toString();
this.emit('data', file);
}));
const license = gulp.src([product.licenseFileName, 'ThirdPartyNotices.txt', 'licenses/**'], { base: '.', allowEmpty: true });
// TODO the API should be copied to `out` during compile, not here
const api = gulp.src('src/vscode-dts/vscode.d.ts').pipe(rename('out/vscode-dts/vscode.d.ts'));
const telemetry = gulp.src('.build/telemetry/**', { base: '.build/telemetry', dot: true });
const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path));
const root = path.resolve(path.join(__dirname, '..'));
const productionDependencies = getProductionDependencies(root);
const dependenciesSrc = productionDependencies.map(d => path.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat().concat('!**/*.mk');
const deps = gulp.src(dependenciesSrc, { base: '.', dot: true })
.pipe(filter(['**', `!**/${config.version}/**`, '!**/bin/darwin-arm64-87/**', '!**/package-lock.json', '!**/yarn.lock', '!**/*.js.map']))
.pipe(util.cleanNodeModules(path.join(__dirname, '.moduleignore')))
.pipe(util.cleanNodeModules(path.join(__dirname, `.moduleignore.${process.platform}`)))
.pipe(jsFilter)
.pipe(util.rewriteSourceMappingURL(sourceMappingURLBase))
.pipe(jsFilter.restore)
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), [
'**/*.node',
'**/@vscode/ripgrep/bin/*',
'**/node-pty/build/Release/*',
'**/node-pty/build/Release/conpty/*',
'**/node-pty/lib/worker/conoutSocketWorker.js',
'**/node-pty/lib/shared/conout.js',
'**/*.wasm',
'**/@vscode/vsce-sign/bin/*',
], [
'**/*.mk',
'!node_modules/vsda/**' // stay compatible with extensions that depend on us shipping `vsda` into ASAR
], [
'node_modules/vsda/**' // retain copy of `vsda` in node_modules for internal use
], 'node_modules.asar'));
let all = es.merge(
packageJsonStream,
productJsonStream,
license,
api,
telemetry,
sources,
deps
);
if (platform === 'win32') {
all = es.merge(all, gulp.src([
'resources/win32/bower.ico',
'resources/win32/c.ico',
'resources/win32/config.ico',
'resources/win32/cpp.ico',
'resources/win32/csharp.ico',
'resources/win32/css.ico',
'resources/win32/default.ico',
'resources/win32/go.ico',
'resources/win32/html.ico',
'resources/win32/jade.ico',
'resources/win32/java.ico',
'resources/win32/javascript.ico',
'resources/win32/json.ico',
'resources/win32/less.ico',
'resources/win32/markdown.ico',
'resources/win32/php.ico',
'resources/win32/powershell.ico',
'resources/win32/python.ico',
'resources/win32/react.ico',
'resources/win32/ruby.ico',
'resources/win32/sass.ico',
'resources/win32/shell.ico',
'resources/win32/sql.ico',
'resources/win32/typescript.ico',
'resources/win32/vue.ico',
'resources/win32/xml.ico',
'resources/win32/yaml.ico',
'resources/win32/code_70x70.png',
'resources/win32/code_150x150.png'
], { base: '.' }));
} else if (platform === 'linux') {
all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' }));
} else if (platform === 'darwin') {
const shortcut = gulp.src('resources/darwin/bin/code.sh')
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('bin/code'));
const policyDest = gulp.src('.build/policies/darwin/**', { base: '.build/policies/darwin' })
.pipe(rename(f => f.dirname = `policies/${f.dirname}`));
all = es.merge(all, shortcut, policyDest);
}
let result = all
.pipe(util.skipDirectories())
.pipe(util.fixWin32DirectoryPermissions())
.pipe(filter(['**', '!**/.github/**'], { dot: true })) // https://github.com/microsoft/vscode/issues/116523
.pipe(electron({ ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, ffmpegChromium: false }))
.pipe(filter(['**', '!LICENSE', '!version'], { dot: true }));
if (platform === 'linux') {
result = es.merge(result, gulp.src('resources/completions/bash/code', { base: '.' })
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(function (f) { f.basename = product.applicationName; })));
result = es.merge(result, gulp.src('resources/completions/zsh/_code', { base: '.' })
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(function (f) { f.basename = '_' + product.applicationName; })));
}
if (platform === 'win32') {
result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32', allowEmpty: true }));
result = es.merge(result, gulp.src('resources/win32/bin/code.cmd', { base: 'resources/win32' })
.pipe(replace('@@NAME@@', product.nameShort))
.pipe(rename(function (f) { f.basename = product.applicationName; })));
result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
.pipe(replace('@@NAME@@', product.nameShort))
.pipe(replace('@@PRODNAME@@', product.nameLong))
.pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(replace('@@SERVERDATAFOLDER@@', product.serverDataFolderName || '.vscode-remote'))
.pipe(replace('@@QUALITY@@', quality))
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
result = es.merge(result, gulp.src('.build/policies/win32/**', { base: '.build/policies/win32' })
.pipe(rename(f => f.dirname = `policies/${f.dirname}`)));
if (quality === 'insider') {
result = es.merge(result, gulp.src('.build/win32/appx/**', { base: '.build/win32' }));
}
} else if (platform === 'linux') {
result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
.pipe(replace('@@PRODNAME@@', product.nameLong))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('bin/' + product.applicationName)));
}
result = inlineMeta(result, {
targetPaths: bootstrapEntryPoints,
packageJsonFn: () => packageJsonContents,
productJsonFn: () => productJsonContents
});
return result.pipe(vfs.dest(destination));
};
}
function patchWin32DependenciesTask(destinationFolderName) {
const cwd = path.join(path.dirname(root), destinationFolderName);
return async () => {
const deps = await glob('**/*.node', { cwd, ignore: 'extensions/node_modules/@parcel/watcher/**' });
const packageJson = JSON.parse(await fs.promises.readFile(path.join(cwd, 'resources', 'app', 'package.json'), 'utf8'));
const product = JSON.parse(await fs.promises.readFile(path.join(cwd, 'resources', 'app', 'product.json'), 'utf8'));
const baseVersion = packageJson.version.replace(/-.*$/, '');
await Promise.all(deps.map(async dep => {
const basename = path.basename(dep);
await rcedit(path.join(cwd, dep), {
'file-version': baseVersion,
'version-string': {
'CompanyName': 'Microsoft Corporation',
'FileDescription': product.nameLong,
'FileVersion': packageJson.version,
'InternalName': basename,
'LegalCopyright': 'Copyright (C) 2022 Microsoft. All rights reserved',
'OriginalFilename': basename,
'ProductName': product.nameLong,
'ProductVersion': packageJson.version,
}
});
}));
};
}
const buildRoot = path.dirname(root);
const BUILD_TARGETS = [
{ platform: 'win32', arch: 'x64' },
{ platform: 'win32', arch: 'arm64' },
{ platform: 'darwin', arch: 'x64', opts: { stats: true } },
{ platform: 'darwin', arch: 'arm64', opts: { stats: true } },
{ platform: 'linux', arch: 'x64' },
{ platform: 'linux', arch: 'armhf' },
{ platform: 'linux', arch: 'arm64' },
];
BUILD_TARGETS.forEach(buildTarget => {
const dashed = (str) => (str ? `-${str}` : ``);
const platform = buildTarget.platform;
const arch = buildTarget.arch;
const opts = buildTarget.opts;
const [vscode, vscodeMin] = ['', 'min'].map(minified => {
const sourceFolderName = `out-vscode${dashed(minified)}`;
const destinationFolderName = `VSCode${dashed(platform)}${dashed(arch)}`;
const tasks = [
compileNativeExtensionsBuildTask,
util.rimraf(path.join(buildRoot, destinationFolderName)),
packageTask(platform, arch, sourceFolderName, destinationFolderName, opts)
];
if (platform === 'win32') {
tasks.push(patchWin32DependenciesTask(destinationFolderName));
}
const vscodeTaskCI = task.define(`vscode${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series(...tasks));
gulp.task(vscodeTaskCI);
const vscodeTask = task.define(`vscode${dashed(platform)}${dashed(arch)}${dashed(minified)}`, task.series(
minified ? compileBuildWithManglingTask : compileBuildWithoutManglingTask,
cleanExtensionsBuildTask,
compileNonNativeExtensionsBuildTask,
compileExtensionMediaBuildTask,
minified ? minifyVSCodeTask : bundleVSCodeTask,
vscodeTaskCI
));
gulp.task(vscodeTask);
return vscodeTask;
});
if (process.platform === platform && process.arch === arch) {
gulp.task(task.define('vscode', task.series(vscode)));
gulp.task(task.define('vscode-min', task.series(vscodeMin)));
}
});
// #region nls
const innoSetupConfig = {
'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } },
'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } },
'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } },
'ja': { codePage: 'CP932' },
'de': { codePage: 'CP1252' },
'fr': { codePage: 'CP1252' },
'es': { codePage: 'CP1252' },
'ru': { codePage: 'CP1251' },
'it': { codePage: 'CP1252' },
'pt-br': { codePage: 'CP1252' },
'hu': { codePage: 'CP1250' },
'tr': { codePage: 'CP1254' }
};
gulp.task(task.define(
'vscode-translations-export',
task.series(
coreCI,
compileAllExtensionsBuildTask,
function () {
const pathToMetadata = './out-build/nls.metadata.json';
const pathToExtensions = '.build/extensions/*';
const pathToSetup = 'build/win32/i18n/messages.en.isl';
return es.merge(
gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
).pipe(vfs.dest('../vscode-translations-export'));
}
)
));
gulp.task('vscode-translations-import', function () {
const options = minimist(process.argv.slice(2), {
string: 'location',
default: {
location: '../vscode-translations-import'
}
});
return es.merge([...i18n.defaultLanguages, ...i18n.extraLanguages].map(language => {
const id = language.id;
return gulp.src(`${options.location}/${id}/vscode-setup/messages.xlf`)
.pipe(i18n.prepareIslFiles(language, innoSetupConfig[language.id]))
.pipe(vfs.dest(`./build/win32/i18n`));
}));
});
// #endregion
================================================
FILE: build/gulpfile.vscode.linux.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 root = path.dirname(__dirname);
const commit = getVersion(root);
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
/**
* @param {string} arch
*/
function getDebPackageArch(arch) {
return { x64: 'amd64', armhf: 'armhf', arm64: 'arm64' }[arch];
}
function prepareDebPackage(arch) {
const binaryDir = '../VSCode-linux-' + arch;
const debArch = getDebPackageArch(arch);
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
return async function () {
const dependencies = await dependenciesGenerator.getDependencies('deb', binaryDir, product.applicationName, debArch);
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
.pipe(rename('usr/share/applications/' + product.applicationName + '.desktop'));
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
.pipe(rename('usr/share/applications/' + product.applicationName + '-url-handler.desktop'));
const desktops = es.merge(desktop, desktopUrlHandler)
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@EXEC@@', `/usr/share/${product.applicationName}/${product.applicationName}`))
.pipe(replace('@@ICON@@', product.linuxIconName))
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@LICENSE@@', product.licenseName))
.pipe(rename('usr/share/appdata/' + product.applicationName + '.appdata.xml'));
const workspaceMime = gulp.src('resources/linux/code-workspace.xml', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('usr/share/mime/packages/' + product.applicationName + '-workspace.xml'));
const icon = gulp.src('resources/linux/code.png', { base: '.' })
.pipe(rename('usr/share/pixmaps/' + product.linuxIconName + '.png'));
const bash_completion = gulp.src('resources/completions/bash/code')
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('usr/share/bash-completion/completions/' + product.applicationName));
const zsh_completion = gulp.src('resources/completions/zsh/_code')
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('usr/share/zsh/vendor-completions/_' + product.applicationName));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; }));
let size = 0;
const control = code.pipe(es.through(
function (f) { size += f.isDirectory() ? 4096 : f.contents.length; },
function () {
const that = this;
gulp.src('resources/linux/debian/control.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', packageJson.version + '-' + linuxPackageRevision))
.pipe(replace('@@ARCHITECTURE@@', debArch))
.pipe(replace('@@DEPENDS@@', dependencies.join(', ')))
.pipe(replace('@@RECOMMENDS@@', debianRecommendedDependencies.join(', ')))
.pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024)))
.pipe(rename('DEBIAN/control'))
.pipe(es.through(function (f) { that.emit('data', f); }, function () { that.emit('end'); }));
}));
const prerm = gulp.src('resources/linux/debian/prerm.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('DEBIAN/prerm'));
const postrm = gulp.src('resources/linux/debian/postrm.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('DEBIAN/postrm'));
const postinst = gulp.src('resources/linux/debian/postinst.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('DEBIAN/postinst'));
const templates = gulp.src('resources/linux/debian/templates.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('DEBIAN/templates'));
const all = es.merge(control, templates, postinst, postrm, prerm, desktops, appdata, workspaceMime, icon, bash_completion, zsh_completion, code);
return all.pipe(vfs.dest(destination));
};
}
/**
* @param {string} arch
*/
function buildDebPackage(arch) {
const debArch = getDebPackageArch(arch);
const cwd = `.build/linux/deb/${debArch}`;
return async () => {
await exec(`chmod 755 ${product.applicationName}-${debArch}/DEBIAN/postinst ${product.applicationName}-${debArch}/DEBIAN/prerm ${product.applicationName}-${debArch}/DEBIAN/postrm`, { cwd });
await exec('mkdir -p deb', { cwd });
await exec(`fakeroot dpkg-deb -Zxz -b ${product.applicationName}-${debArch} deb`, { cwd });
};
}
/**
* @param {string} rpmArch
*/
function getRpmBuildPath(rpmArch) {
return '.build/linux/rpm/' + rpmArch + '/rpmbuild';
}
/**
* @param {string} arch
*/
function getRpmPackageArch(arch) {
return { x64: 'x86_64', armhf: 'armv7hl', arm64: 'aarch64' }[arch];
}
/**
* @param {string} arch
*/
function prepareRpmPackage(arch) {
const binaryDir = '../VSCode-linux-' + arch;
const rpmArch = getRpmPackageArch(arch);
const stripBinary = process.env['STRIP'] ?? '/usr/bin/strip';
return async function () {
const dependencies = await dependenciesGenerator.getDependencies('rpm', binaryDir, product.applicationName, rpmArch);
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '.desktop'));
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '-url-handler.desktop'));
const desktops = es.merge(desktop, desktopUrlHandler)
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@EXEC@@', `/usr/share/${product.applicationName}/${product.applicationName}`))
.pipe(replace('@@ICON@@', product.linuxIconName))
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@LICENSE@@', product.licenseName))
.pipe(rename('BUILD/usr/share/appdata/' + product.applicationName + '.appdata.xml'));
const workspaceMime = gulp.src('resources/linux/code-workspace.xml', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('BUILD/usr/share/mime/packages/' + product.applicationName + '-workspace.xml'));
const icon = gulp.src('resources/linux/code.png', { base: '.' })
.pipe(rename('BUILD/usr/share/pixmaps/' + product.linuxIconName + '.png'));
const bash_completion = gulp.src('resources/completions/bash/code')
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('BUILD/usr/share/bash-completion/completions/' + product.applicationName));
const zsh_completion = gulp.src('resources/completions/zsh/_code')
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('BUILD/usr/share/zsh/site-functions/_' + product.applicationName));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = 'BUILD/usr/share/' + product.applicationName + '/' + p.dirname; }));
const spec = gulp.src('resources/linux/rpm/code.spec.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@ICON@@', product.linuxIconName))
.pipe(replace('@@VERSION@@', packageJson.version))
.pipe(replace('@@RELEASE@@', linuxPackageRevision))
.pipe(replace('@@ARCHITECTURE@@', rpmArch))
.pipe(replace('@@LICENSE@@', product.licenseName))
.pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@'))
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@'))
.pipe(replace('@@DEPENDENCIES@@', dependencies.join(', ')))
.pipe(replace('@@STRIP@@', stripBinary))
.pipe(rename('SPECS/' + product.applicationName + '.spec'));
const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' })
.pipe(rename('SOURCES/' + product.applicationName + '.xpm'));
const all = es.merge(code, desktops, appdata, workspaceMime, icon, bash_completion, zsh_completion, spec, specIcon);
return all.pipe(vfs.dest(getRpmBuildPath(rpmArch)));
};
}
/**
* @param {string} arch
*/
function buildRpmPackage(arch) {
const rpmArch = getRpmPackageArch(arch);
const rpmBuildPath = getRpmBuildPath(rpmArch);
const rpmOut = `${rpmBuildPath}/RPMS/${rpmArch}`;
const destination = `.build/linux/rpm/${rpmArch}`;
return async () => {
await exec(`mkdir -p ${destination}`);
await exec(`HOME="$(pwd)/${destination}" rpmbuild -bb ${rpmBuildPath}/SPECS/${product.applicationName}.spec --target=${rpmArch}`);
await exec(`cp "${rpmOut}/$(ls ${rpmOut})" ${destination}/`);
};
}
/**
* @param {string} arch
*/
function getSnapBuildPath(arch) {
return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`;
}
/**
* @param {string} arch
*/
function prepareSnapPackage(arch) {
const binaryDir = '../VSCode-linux-' + arch;
const destination = getSnapBuildPath(arch);
return function () {
// A desktop file that is placed in snap/gui will be placed into meta/gui verbatim.
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
.pipe(rename(`snap/gui/${product.applicationName}.desktop`));
// A desktop file that is placed in snap/gui will be placed into meta/gui verbatim.
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
.pipe(rename(`snap/gui/${product.applicationName}-url-handler.desktop`));
const desktops = es.merge(desktop, desktopUrlHandler)
.pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@EXEC@@', `${product.applicationName} --force-user-env`))
.pipe(replace('@@ICON@@', `\${SNAP}/meta/gui/${product.linuxIconName}.png`))
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
// An icon that is placed in snap/gui will be placed into meta/gui verbatim.
const icon = gulp.src('resources/linux/code.png', { base: '.' })
.pipe(rename(`snap/gui/${product.linuxIconName}.png`));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = `usr/share/${product.applicationName}/${p.dirname}`; }));
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', commit.substr(0, 8)))
// Possible run-on values https://snapcraft.io/docs/architectures
.pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch))
.pipe(rename('snap/snapcraft.yaml'));
const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' })
.pipe(rename('electron-launch'));
const all = es.merge(desktops, icon, code, snapcraft, electronLaunch);
return all.pipe(vfs.dest(destination));
};
}
/**
* @param {string} arch
*/
function buildSnapPackage(arch) {
const cwd = getSnapBuildPath(arch);
return () => exec('snapcraft', { cwd });
}
const BUILD_TARGETS = [
{ arch: 'x64' },
{ arch: 'armhf' },
{ arch: 'arm64' },
];
BUILD_TARGETS.forEach(({ arch }) => {
const debArch = getDebPackageArch(arch);
const prepareDebTask = task.define(`vscode-linux-${arch}-prepare-deb`, task.series(rimraf(`.build/linux/deb/${debArch}`), prepareDebPackage(arch)));
gulp.task(prepareDebTask);
const buildDebTask = task.define(`vscode-linux-${arch}-build-deb`, buildDebPackage(arch));
gulp.task(buildDebTask);
const rpmArch = getRpmPackageArch(arch);
const prepareRpmTask = task.define(`vscode-linux-${arch}-prepare-rpm`, task.series(rimraf(`.build/linux/rpm/${rpmArch}`), prepareRpmPackage(arch)));
gulp.task(prepareRpmTask);
const buildRpmTask = task.define(`vscode-linux-${arch}-build-rpm`, buildRpmPackage(arch));
gulp.task(buildRpmTask);
const prepareSnapTask = task.define(`vscode-linux-${arch}-prepare-snap`, task.series(rimraf(`.build/linux/snap/${arch}`), prepareSnapPackage(arch)));
gulp.task(prepareSnapTask);
const buildSnapTask = task.define(`vscode-linux-${arch}-build-snap`, task.series(prepareSnapTask, buildSnapPackage(arch)));
gulp.task(buildSnapTask);
});
================================================
FILE: build/gulpfile.vscode.web.js
================================================
/*---------------------------------------------------------------------------------------------
* 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 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 REPO_ROOT = path.dirname(__dirname);
const BUILD_ROOT = path.dirname(REPO_ROOT);
const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web');
const commit = getVersion(REPO_ROOT);
const quality = product.quality;
const version = (quality && quality !== 'stable') ? `${packageJson.version}-${quality}` : packageJson.version;
const vscodeWebResourceIncludes = [
// NLS
'out-build/nls.messages.js',
// Accessibility Signals
'out-build/vs/platform/accessibilitySignal/browser/media/*.mp3',
// Welcome
'out-build/vs/workbench/contrib/welcomeGettingStarted/common/media/**/*.{svg,png}',
// Extensions
'out-build/vs/workbench/contrib/extensions/browser/media/{theme-icon.png,language-icon.svg}',
'out-build/vs/workbench/services/extensionManagement/common/media/*.{svg,png}',
// Webview
'out-build/vs/workbench/contrib/webview/browser/pre/*.{js,html}',
// Tree Sitter highlights
'out-build/vs/editor/common/languages/highlights/*.scm',
// Tree Sitter injections
'out-build/vs/editor/common/languages/injections/*.scm',
// Extension Host Worker
'out-build/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html',
];
exports.vscodeWebResourceIncludes = vscodeWebResourceIncludes;
const vscodeWebResources = [
// Includes
...vscodeWebResourceIncludes,
// Excludes
'!out-build/vs/**/{node,electron-sandbox,electron-main,electron-utility}/**',
'!out-build/vs/editor/standalone/**',
'!out-build/vs/workbench/**/*-tb.png',
'!out-build/vs/code/**/*-dev.html',
'!**/test/**'
];
const buildfile = require('./buildfile');
const vscodeWebEntryPoints = [
buildfile.workerEditor,
buildfile.workerExtensionHost,
buildfile.workerNotebook,
buildfile.workerLanguageDetection,
buildfile.workerLocalFileSearch,
buildfile.workerOutputLinks,
buildfile.workerBackgroundTokenization,
buildfile.keyboardMaps,
buildfile.workbenchWeb,
buildfile.entrypoint('vs/workbench/workbench.web.main.internal') // TODO@esm remove line when we stop supporting web-amd-esm-bridge
].flat();
/**
* @param extensionsRoot {string} The location where extension will be read from
* @param {object} product The parsed product.json file contents
*/
const createVSCodeWebFileContentMapper = (extensionsRoot, product) => {
return path => {
if (path.endsWith('vs/platform/product/common/product.js')) {
return content => {
const productConfiguration = JSON.stringify({
...product,
version,
commit,
date: readISODate('out-build')
});
return content.replace('/*BUILD->INSERT_PRODUCT_CONFIGURATION*/', () => productConfiguration.substr(1, productConfiguration.length - 2) /* without { and }*/);
};
} else if (path.endsWith('vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.js')) {
return content => {
const builtinExtensions = JSON.stringify(extensions.scanBuiltinExtensions(extensionsRoot));
return content.replace('/*BUILD->INSERT_BUILTIN_EXTENSIONS*/', () => builtinExtensions.substr(1, builtinExtensions.length - 2) /* without [ and ]*/);
};
}
return undefined;
};
};
exports.createVSCodeWebFileContentMapper = createVSCodeWebFileContentMapper;
const bundleVSCodeWebTask = task.define('bundle-vscode-web', task.series(
util.rimraf('out-vscode-web'),
optimize.bundleTask(
{
out: 'out-vscode-web',
esm: {
src: 'out-build',
entryPoints: vscodeWebEntryPoints,
resources: vscodeWebResources,
fileContentMapper: createVSCodeWebFileContentMapper('.build/web/extensions', product)
}
}
)
));
const minifyVSCodeWebTask = task.define('minify-vscode-web', task.series(
bundleVSCodeWebTask,
util.rimraf('out-vscode-web-min'),
optimize.minifyTask('out-vscode-web', `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
));
gulp.task(minifyVSCodeWebTask);
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'); }));
const extensions = gulp.src('.build/web/extensions/**', { base: '.build/web', dot: true });
const loader = gulp.src('build/loader.min', { base: 'build', dot: true }).pipe(rename('out/vs/loader.js')); // TODO@esm remove line when we stop supporting web-amd-esm-bridge
const sources = es.merge(src, extensions, loader)
.pipe(filter(['**', '!**/*.js.map'], { dot: true }))
// TODO@esm remove me once we stop supporting our web-esm-bridge
.pipe(es.through(function (file) {
if (file.relative === 'out/vs/workbench/workbench.web.main.internal.css') {
this.emit('data', new VinylFile({
contents: file.contents,
path: file.path.replace('workbench.web.main.internal.css', 'workbench.web.main.css'),
base: file.base
}));
}
this.emit('data', file);
}));
const name = product.nameShort;
const packageJsonStream = gulp.src(['remote/web/package.json'], { base: 'remote/web' })
.pipe(json({ name, version }));
const license = gulp.src(['remote/LICENSE'], { base: 'remote', allowEmpty: true });
const productionDependencies = getProductionDependencies(WEB_FOLDER);
const dependenciesSrc = productionDependencies.map(d => path.relative(REPO_ROOT, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`, `!${d}/.bin/**`]).flat();
const deps = gulp.src(dependenciesSrc, { base: 'remote/web', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
.pipe(util.cleanNodeModules(path.join(__dirname, '.webignore')));
const favicon = gulp.src('resources/server/favicon.ico', { base: 'resources/server' });
const manifest = gulp.src('resources/server/manifest.json', { base: 'resources/server' });
const pwaicons = es.merge(
gulp.src('resources/server/code-192.png', { base: 'resources/server' }),
gulp.src('resources/server/code-512.png', { base: 'resources/server' })
);
const all = es.merge(
packageJsonStream,
license,
sources,
deps,
favicon,
manifest,
pwaicons
);
const result = all
.pipe(util.skipDirectories())
.pipe(util.fixWin32DirectoryPermissions());
return result.pipe(vfs.dest(destination));
};
}
const compileWebExtensionsBuildTask = task.define('compile-web-extensions-build', task.series(
task.define('clean-web-extensions-build', util.rimraf('.build/web/extensions')),
task.define('bundle-web-extensions-build', () => extensions.packageAllLocalExtensionsStream(true, false).pipe(gulp.dest('.build/web'))),
task.define('bundle-marketplace-web-extensions-build', () => extensions.packageMarketplaceExtensionsStream(true).pipe(gulp.dest('.build/web'))),
task.define('bundle-web-extension-media-build', () => extensions.buildExtensionMedia(false, '.build/web/extensions')),
));
gulp.task(compileWebExtensionsBuildTask);
const dashed = (/** @type {string} */ str) => (str ? `-${str}` : ``);
['', 'min'].forEach(minified => {
const sourceFolderName = `out-vscode-web${dashed(minified)}`;
const destinationFolderName = `vscode-web`;
const vscodeWebTaskCI = task.define(`vscode-web${dashed(minified)}-ci`, task.series(
compileWebExtensionsBuildTask,
minified ? minifyVSCodeWebTask : bundleVSCodeWebTask,
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
packageTask(sourceFolderName, destinationFolderName)
));
gulp.task(vscodeWebTaskCI);
const vscodeWebTask = task.define(`vscode-web${dashed(minified)}`, task.series(
compileBuildWithManglingTask,
vscodeWebTaskCI
));
gulp.task(vscodeWebTask);
});
================================================
FILE: build/gulpfile.vscode.win32.js
================================================
/*---------------------------------------------------------------------------------------------
* 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');
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`);
const issPath = path.join(__dirname, 'win32', 'code.iss');
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup'))), 'bin', 'ISCC.exe');
const signWin32Path = path.join(repoPath, 'build', 'azure-pipelines', 'common', 'sign-win32');
function packageInnoSetup(iss, options, cb) {
options = options || {};
const definitions = options.definitions || {};
if (process.argv.some(arg => arg === '--debug-inno')) {
definitions['Debug'] = 'true';
}
if (process.argv.some(arg => arg === '--sign')) {
definitions['Sign'] = 'true';
}
const keys = Object.keys(definitions);
keys.forEach(key => assert(typeof definitions[key] === 'string', `Missing value for '${key}' in Inno Setup package step`));
const defs = keys.map(key => `/d${key}=${definitions[key]}`);
const args = [
iss,
...defs,
`/sesrp=node ${signWin32Path} $f`
];
cp.spawn(innoSetupPath, args, { stdio: ['ignore', 'inherit', 'inherit'] })
.on('error', cb)
.on('exit', code => {
if (code === 0) {
cb(null);
} else {
cb(new Error(`InnoSetup returned exit code: ${code}`));
}
});
}
/**
* @param {string} arch
* @param {string} target
*/
function buildWin32Setup(arch, target) {
if (target !== 'system' && target !== 'user') {
throw new Error('Invalid setup target');
}
return cb => {
const x64AppId = target === 'system' ? product.win32x64AppId : product.win32x64UserAppId;
const arm64AppId = target === 'system' ? product.win32arm64AppId : product.win32arm64UserAppId;
const sourcePath = buildPath(arch);
const outputPath = setupDir(arch, target);
fs.mkdirSync(outputPath, { recursive: true });
const originalProductJsonPath = path.join(sourcePath, 'resources/app/product.json');
const productJsonPath = path.join(outputPath, 'product.json');
const productJson = JSON.parse(fs.readFileSync(originalProductJsonPath, 'utf8'));
productJson['target'] = target;
fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t'));
const quality = product.quality || 'dev';
const definitions = {
NameLong: product.nameLong,
NameShort: product.nameShort,
DirName: product.win32DirName,
Version: pkg.version,
RawVersion: pkg.version.replace(/-\w+$/, ''),
NameVersion: product.win32NameVersion + (target === 'user' ? ' (User)' : ''),
ExeBasename: product.nameShort,
RegValueName: product.win32RegValueName,
ShellNameShort: product.win32ShellNameShort,
AppMutex: product.win32MutexName,
TunnelMutex: product.win32TunnelMutex,
TunnelServiceMutex: product.win32TunnelServiceMutex,
TunnelApplicationName: product.tunnelApplicationName,
ApplicationName: product.applicationName,
Arch: arch,
AppId: { 'x64': x64AppId, 'arm64': arm64AppId }[arch],
IncompatibleTargetAppId: { 'x64': product.win32x64AppId, 'arm64': product.win32arm64AppId }[arch],
AppUserId: product.win32AppUserModelId,
ArchitecturesAllowed: { 'x64': 'x64', 'arm64': 'arm64' }[arch],
ArchitecturesInstallIn64BitMode: { 'x64': 'x64', 'arm64': 'arm64' }[arch],
SourceDir: sourcePath,
RepoDir: repoPath,
OutputDir: outputPath,
InstallTarget: target,
ProductJsonPath: productJsonPath,
Quality: quality
};
if (quality === 'insider') {
definitions['AppxPackage'] = `code_insiders_explorer_${arch}.appx`;
definitions['AppxPackageFullname'] = `Microsoft.${product.win32RegValueName}_1.0.0.0_neutral__8wekyb3d8bbwe`;
}
packageInnoSetup(issPath, { definitions }, cb);
};
}
/**
* @param {string} arch
* @param {string} target
*/
function defineWin32SetupTasks(arch, target) {
const cleanTask = util.rimraf(setupDir(arch, target));
gulp.task(task.define(`vscode-win32-${arch}-${target}-setup`, task.series(cleanTask, buildWin32Setup(arch, target))));
}
defineWin32SetupTasks('x64', 'system');
defineWin32SetupTasks('arm64', 'system');
defineWin32SetupTasks('x64', 'user');
defineWin32SetupTasks('arm64', 'user');
/**
* @param {string} arch
*/
function copyInnoUpdater(arch) {
return () => {
return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' })
.pipe(vfs.dest(path.join(buildPath(arch), 'tools')));
};
}
/**
* @param {string} executablePath
*/
function updateIcon(executablePath) {
return cb => {
const icon = path.join(repoPath, 'resources', 'win32', 'code.ico');
rcedit(executablePath, { icon }, cb);
};
}
gulp.task(task.define('vscode-win32-x64-inno-updater', task.series(copyInnoUpdater('x64'), updateIcon(path.join(buildPath('x64'), 'tools', 'inno_updater.exe')))));
gulp.task(task.define('vscode-win32-arm64-inno-updater', task.series(copyInnoUpdater('arm64'), updateIcon(path.join(buildPath('arm64'), 'tools', 'inno_updater.exe')))));
================================================
FILE: build/hygiene.js
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
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');
const copyrightHeaderLines = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the MIT License. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/',
];
function hygiene(some, linting = true) {
const eslint = require('./gulp-eslint');
const gulpstylelint = require('./stylelint');
const formatter = require('./lib/formatter');
let errorCount = 0;
const productJson = es.through(function (file) {
const product = JSON.parse(file.contents.toString('utf8'));
if (product.extensionsGallery) {
console.error(`product.json: Contains 'extensionsGallery'`);
errorCount++;
}
this.emit('data', file);
});
const unicode = es.through(function (file) {
const lines = file.contents.toString('utf8').split(/\r\n|\r|\n/);
file.__lines = lines;
const allowInComments = lines.some(line => /allow-any-unicode-comment-file/.test(line));
let skipNext = false;
lines.forEach((line, i) => {
if (/allow-any-unicode-next-line/.test(line)) {
skipNext = true;
return;
}
if (skipNext) {
skipNext = false;
return;
}
// If unicode is allowed in comments, trim the comment from the line
if (allowInComments) {
if (line.match(/\s+(\*)/)) { // Naive multi-line comment check
line = '';
} else {
const index = line.indexOf('\/\/');
line = index === -1 ? line : line.substring(0, index);
}
}
// Please do not add symbols that resemble ASCII letters!
// eslint-disable-next-line no-misleading-character-class
const m = /([^\t\n\r\x20-\x7E⊃⊇✔︎✓🎯⚠️🛑🔴🚗🚙🚕🎉✨❗⇧⌥⌘×÷¦⋯…↑↓→→←↔⟷·•●◆▼⟪⟫┌└├⏎↩√φ]+)/g.exec(line);
if (m) {
console.error(
file.relative + `(${i + 1},${m.index + 1}): Unexpected unicode character: "${m[0]}" (charCode: ${m[0].charCodeAt(0)}). To suppress, use // allow-any-unicode-next-line`
);
errorCount++;
}
});
this.emit('data', file);
});
const indentation = es.through(function (file) {
const lines = file.__lines || file.contents.toString('utf8').split(/\r\n|\r|\n/);
file.__lines = lines;
lines.forEach((line, i) => {
if (/^\s*$/.test(line)) {
// empty or whitespace lines are OK
} else if (/^[\t]*[^\s]/.test(line)) {
// good indent
} else if (/^[\t]* \*/.test(line)) {
// block comment using an extra space
} else {
console.error(
file.relative + '(' + (i + 1) + ',1): Bad whitespace indentation'
);
errorCount++;
}
});
this.emit('data', file);
});
const copyrights = es.through(function (file) {
const lines = file.__lines;
for (let i = 0; i < copyrightHeaderLines.length; i++) {
if (lines[i] !== copyrightHeaderLines[i]) {
console.error(file.relative + ': Missing or bad copyright statement');
errorCount++;
break;
}
}
this.emit('data', file);
});
const formatting = es.map(function (file, cb) {
try {
const rawInput = file.contents.toString('utf8');
const rawOutput = formatter.format(file.path, rawInput);
const original = rawInput.replace(/\r\n/gm, '\n');
const formatted = rawOutput.replace(/\r\n/gm, '\n');
if (original !== formatted) {
console.error(
`File not formatted. Run the 'Format Document' command to fix it:`,
file.relative
);
errorCount++;
}
cb(null, file);
} catch (err) {
cb(err);
}
});
let input;
if (Array.isArray(some) || typeof some === 'string' || !some) {
const options = { base: '.', follow: true, allowEmpty: true };
if (some) {
input = vfs.src(some, options).pipe(filter(all)); // split this up to not unnecessarily filter all a second time
} else {
input = vfs.src(all, options);
}
} else {
input = some;
}
const productJsonFilter = filter('product.json', { restore: true });
const snapshotFilter = filter(['**', '!**/*.snap', '!**/*.snap.actual']);
const yarnLockFilter = filter(['**', '!**/yarn.lock']);
const unicodeFilterStream = filter(unicodeFilter, { restore: true });
const result = input
.pipe(filter((f) => !f.stat.isDirectory()))
.pipe(snapshotFilter)
.pipe(yarnLockFilter)
.pipe(productJsonFilter)
.pipe(process.env['BUILD_SOURCEVERSION'] ? es.through() : productJson)
.pipe(productJsonFilter.restore)
.pipe(unicodeFilterStream)
.pipe(unicode)
.pipe(unicodeFilterStream.restore)
.pipe(filter(indentationFilter))
.pipe(indentation)
.pipe(filter(copyrightFilter))
.pipe(copyrights);
const streams = [
result.pipe(filter(tsFormattingFilter)).pipe(formatting)
];
if (linting) {
streams.push(
result
.pipe(filter(eslintFilter))
.pipe(
eslint((results) => {
errorCount += results.warningCount;
errorCount += results.errorCount;
})
)
);
streams.push(
result.pipe(filter(stylelintFilter)).pipe(gulpstylelint(((message, isError) => {
if (isError) {
console.error(message);
errorCount++;
} else {
console.warn(message);
}
})))
);
}
let count = 0;
return es.merge(...streams).pipe(
es.through(
function (data) {
count++;
if (process.env['TRAVIS'] && count % 10 === 0) {
process.stdout.write('.');
}
this.emit('data', data);
},
function () {
process.stdout.write('\n');
if (errorCount > 0) {
this.emit(
'error',
'Hygiene failed with ' +
errorCount +
` errors. Check 'build / gulpfile.hygiene.js'.`
);
} else {
this.emit('end');
}
}
)
);
}
module.exports.hygiene = hygiene;
function createGitIndexVinyls(paths) {
const cp = require('child_process');
const repositoryPath = process.cwd();
const fns = paths.map((relativePath) => () =>
new Promise((c, e) => {
const fullPath = path.join(repositoryPath, relativePath);
fs.stat(fullPath, (err, stat) => {
if (err && err.code === 'ENOENT') {
// ignore deletions
return c(null);
} else if (err) {
return e(err);
}
cp.exec(
process.platform === 'win32' ? `git show :${relativePath}` : `git show ':${relativePath}'`,
{ maxBuffer: stat.size, encoding: 'buffer' },
(err, out) => {
if (err) {
return e(err);
}
c(
new VinylFile({
path: fullPath,
base: repositoryPath,
contents: out,
stat,
})
);
}
);
});
})
);
return pall(fns, { concurrency: 4 }).then((r) => r.filter((p) => !!p));
}
// Void - NO PRE COMMIT HOOKS!!!! for now... - Void team
// // this allows us to run hygiene as a git pre-commit hook
// if (require.main === module) {
// const cp = require('child_process');
// process.on('unhandledRejection', (reason, p) => {
// console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
// process.exit(1);
// });
// if (process.argv.length > 2) {
// hygiene(process.argv.slice(2)).on('error', (err) => {
// console.error();
// console.error(err);
// process.exit(1);
// });
// } else {
// cp.exec(
// 'git diff --cached --name-only',
// { maxBuffer: 2000 * 1024 },
// (err, out) => {
// if (err) {
// console.error();
// console.error(err);
// process.exit(1);
// }
// const some = out.split(/\r?\n/).filter((l) => !!l);
// if (some.length > 0) {
// console.log('Reading git index versions...');
// createGitIndexVinyls(some)
// .then(
// (vinyls) =>
// new Promise((c, e) =>
// hygiene(es.readArray(vinyls).pipe(filter(all)))
// .on('end', () => c())
// .on('error', e)
// )
// )
// .catch((err) => {
// console.error();
// console.error(err);
// process.exit(1);
// });
// }
// }
// );
// }
// }
================================================
FILE: build/lib/asar.js
================================================
"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;
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 vinyl_1 = __importDefault(require("vinyl"));
const minimatch_1 = __importDefault(require("minimatch"));
function createAsar(folderPath, unpackGlobs, skipGlobs, duplicateGlobs, destFilename) {
const shouldUnpackFile = (file) => {
for (let i = 0; i < unpackGlobs.length; i++) {
if ((0, minimatch_1.default)(file.relative, unpackGlobs[i])) {
return true;
}
}
return false;
};
const shouldSkipFile = (file) => {
for (const skipGlob of skipGlobs) {
if ((0, minimatch_1.default)(file.relative, skipGlob)) {
return true;
}
}
return false;
};
// Files that should be duplicated between
// node_modules.asar and node_modules
const shouldDuplicateFile = (file) => {
for (const duplicateGlob of duplicateGlobs) {
if ((0, minimatch_1.default)(file.relative, duplicateGlob)) {
return true;
}
}
return false;
};
const filesystem = new Filesystem(folderPath);
const out = [];
// Keep track of pending inserts
let pendingInserts = 0;
let onFileInserted = () => { pendingInserts--; };
// Do not insert twice the same directory
const seenDir = {};
const insertDirectoryRecursive = (dir) => {
if (seenDir[dir]) {
return;
}
let lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
filesystem.insertDirectory(dir);
};
const insertDirectoryForFile = (file) => {
let lastSlash = file.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = file.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(file.substring(0, lastSlash));
}
};
const insertFile = (relativePath, stat, shouldUnpack) => {
insertDirectoryForFile(relativePath);
pendingInserts++;
// Do not pass `onFileInserted` directly because it gets overwritten below.
// Create a closure capturing `onFileInserted`.
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => onFileInserted());
};
return event_stream_1.default.through(function (file) {
if (file.stat.isDirectory()) {
return;
}
if (!file.stat.isFile()) {
throw new Error(`unknown item in stream!`);
}
if (shouldSkipFile(file)) {
this.queue(new vinyl_1.default({
base: '.',
path: file.path,
stat: file.stat,
contents: file.contents
}));
return;
}
if (shouldDuplicateFile(file)) {
this.queue(new vinyl_1.default({
base: '.',
path: file.path,
stat: file.stat,
contents: file.contents
}));
}
const shouldUnpack = shouldUnpackFile(file);
insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
if (shouldUnpack) {
// The file goes outside of xx.asar, in a folder xx.asar.unpacked
const relative = path_1.default.relative(folderPath, file.path);
this.queue(new vinyl_1.default({
base: '.',
path: path_1.default.join(destFilename + '.unpacked', relative),
stat: file.stat,
contents: file.contents
}));
}
else {
// The file goes inside of xx.asar
out.push(file.contents);
}
}, function () {
const finish = () => {
{
const headerPickle = pickle.createEmpty();
headerPickle.writeString(JSON.stringify(filesystem.header));
const headerBuf = headerPickle.toBuffer();
const sizePickle = pickle.createEmpty();
sizePickle.writeUInt32(headerBuf.length);
const sizeBuf = sizePickle.toBuffer();
out.unshift(headerBuf);
out.unshift(sizeBuf);
}
const contents = Buffer.concat(out);
out.length = 0;
this.queue(new vinyl_1.default({
base: '.',
path: destFilename,
contents: contents
}));
this.queue(null);
};
// Call finish() only when all file inserts have finished...
if (pendingInserts === 0) {
finish();
}
else {
onFileInserted = () => {
pendingInserts--;
if (pendingInserts === 0) {
finish();
}
};
}
});
}
//# sourceMappingURL=asar.js.map
================================================
FILE: build/lib/asar.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import path from 'path';
import es from 'event-stream';
const pickle = require('chromium-pickle-js');
const Filesystem = require('asar/lib/filesystem');
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 => {
for (let i = 0; i < unpackGlobs.length; i++) {
if (minimatch(file.relative, unpackGlobs[i])) {
return true;
}
}
return false;
};
const shouldSkipFile = (file: VinylFile): boolean => {
for (const skipGlob of skipGlobs) {
if (minimatch(file.relative, skipGlob)) {
return true;
}
}
return false;
};
// Files that should be duplicated between
// node_modules.asar and node_modules
const shouldDuplicateFile = (file: VinylFile): boolean => {
for (const duplicateGlob of duplicateGlobs) {
if (minimatch(file.relative, duplicateGlob)) {
return true;
}
}
return false;
};
const filesystem = new Filesystem(folderPath);
const out: Buffer[] = [];
// Keep track of pending inserts
let pendingInserts = 0;
let onFileInserted = () => { pendingInserts--; };
// Do not insert twice the same directory
const seenDir: { [key: string]: boolean } = {};
const insertDirectoryRecursive = (dir: string) => {
if (seenDir[dir]) {
return;
}
let lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
filesystem.insertDirectory(dir);
};
const insertDirectoryForFile = (file: string) => {
let lastSlash = file.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = file.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(file.substring(0, lastSlash));
}
};
const insertFile = (relativePath: string, stat: { size: number; mode: number }, shouldUnpack: boolean) => {
insertDirectoryForFile(relativePath);
pendingInserts++;
// Do not pass `onFileInserted` directly because it gets overwritten below.
// Create a closure capturing `onFileInserted`.
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => onFileInserted());
};
return es.through(function (file) {
if (file.stat.isDirectory()) {
return;
}
if (!file.stat.isFile()) {
throw new Error(`unknown item in stream!`);
}
if (shouldSkipFile(file)) {
this.queue(new VinylFile({
base: '.',
path: file.path,
stat: file.stat,
contents: file.contents
}));
return;
}
if (shouldDuplicateFile(file)) {
this.queue(new VinylFile({
base: '.',
path: file.path,
stat: file.stat,
contents: file.contents
}));
}
const shouldUnpack = shouldUnpackFile(file);
insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
if (shouldUnpack) {
// The file goes outside of xx.asar, in a folder xx.asar.unpacked
const relative = path.relative(folderPath, file.path);
this.queue(new VinylFile({
base: '.',
path: path.join(destFilename + '.unpacked', relative),
stat: file.stat,
contents: file.contents
}));
} else {
// The file goes inside of xx.asar
out.push(file.contents);
}
}, function () {
const finish = () => {
{
const headerPickle = pickle.createEmpty();
headerPickle.writeString(JSON.stringify(filesystem.header));
const headerBuf = headerPickle.toBuffer();
const sizePickle = pickle.createEmpty();
sizePickle.writeUInt32(headerBuf.length);
const sizeBuf = sizePickle.toBuffer();
out.unshift(headerBuf);
out.unshift(sizeBuf);
}
const contents = Buffer.concat(out);
out.length = 0;
this.queue(new VinylFile({
base: '.',
path: destFilename,
contents: contents
}));
this.queue(null);
};
// Call finish() only when all file inserts have finished...
if (pendingInserts === 0) {
finish();
} else {
onFileInserted = () => {
pendingInserts--;
if (pendingInserts === 0) {
finish();
}
};
}
});
}
================================================
FILE: build/lib/builtInExtensions.js
================================================
"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 });
exports.getExtensionStream = getExtensionStream;
exports.getBuiltInExtensions = getBuiltInExtensions;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const os_1 = __importDefault(require("os"));
const rimraf_1 = __importDefault(require("rimraf"));
const event_stream_1 = __importDefault(require("event-stream"));
const gulp_rename_1 = __importDefault(require("gulp-rename"));
const vinyl_fs_1 = __importDefault(require("vinyl-fs"));
const ext = __importStar(require("./extensions"));
const fancy_log_1 = __importDefault(require("fancy-log"));
const ansi_colors_1 = __importDefault(require("ansi-colors"));
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
const productjson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = productjson.builtInExtensions || [];
const webBuiltInExtensions = productjson.webBuiltInExtensions || [];
const controlFilePath = path_1.default.join(os_1.default.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
const ENABLE_LOGGING = !process.env['VSCODE_BUILD_BUILTIN_EXTENSIONS_SILENCE_PLEASE'];
function log(...messages) {
if (ENABLE_LOGGING) {
(0, fancy_log_1.default)(...messages);
}
}
function getExtensionPath(extension) {
return path_1.default.join(root, '.build', 'builtInExtensions', extension.name);
}
function isUpToDate(extension) {
const packagePath = path_1.default.join(getExtensionPath(extension), 'package.json');
if (!fs_1.default.existsSync(packagePath)) {
return false;
}
const packageContents = fs_1.default.readFileSync(packagePath, { encoding: 'utf8' });
try {
const diskVersion = JSON.parse(packageContents).version;
return (diskVersion === extension.version);
}
catch (err) {
return false;
}
}
function getExtensionDownloadStream(extension) {
let input;
if (extension.vsix) {
input = ext.fromVsix(path_1.default.join(root, extension.vsix), extension);
}
else if (productjson.extensionsGallery?.serviceUrl) {
input = ext.fromMarketplace(productjson.extensionsGallery.serviceUrl, extension);
}
else {
input = ext.fromGithub(extension);
}
return input.pipe((0, gulp_rename_1.default)(p => p.dirname = `${extension.name}/${p.dirname}`));
}
function getExtensionStream(extension) {
// if the extension exists on disk, use those files instead of downloading anew
if (isUpToDate(extension)) {
log('[extensions]', `${extension.name}@${extension.version} up to date`, ansi_colors_1.default.green('✔︎'));
return vinyl_fs_1.default.src(['**'], { cwd: getExtensionPath(extension), dot: true })
.pipe((0, gulp_rename_1.default)(p => p.dirname = `${extension.name}/${p.dirname}`));
}
return getExtensionDownloadStream(extension);
}
function syncMarketplaceExtension(extension) {
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
const source = ansi_colors_1.default.blue(galleryServiceUrl ? '[marketplace]' : '[github]');
if (isUpToDate(extension)) {
log(source, `${extension.name}@${extension.version}`, ansi_colors_1.default.green('✔︎'));
return event_stream_1.default.readArray([]);
}
rimraf_1.default.sync(getExtensionPath(extension));
return getExtensionDownloadStream(extension)
.pipe(vinyl_fs_1.default.dest('.build/builtInExtensions'))
.on('end', () => log(source, extension.name, ansi_colors_1.default.green('✔︎')));
}
function syncExtension(extension, controlState) {
if (extension.platforms) {
const platforms = new Set(extension.platforms);
if (!platforms.has(process.platform)) {
log(ansi_colors_1.default.gray('[skip]'), `${extension.name}@${extension.version}: Platform '${process.platform}' not supported: [${extension.platforms}]`, ansi_colors_1.default.green('✔︎'));
return event_stream_1.default.readArray([]);
}
}
switch (controlState) {
case 'disabled':
log(ansi_colors_1.default.blue('[disabled]'), ansi_colors_1.default.gray(extension.name));
return event_stream_1.default.readArray([]);
case 'marketplace':
return syncMarketplaceExtension(extension);
default:
if (!fs_1.default.existsSync(controlState)) {
log(ansi_colors_1.default.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`));
return event_stream_1.default.readArray([]);
}
else if (!fs_1.default.existsSync(path_1.default.join(controlState, 'package.json'))) {
log(ansi_colors_1.default.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`));
return event_stream_1.default.readArray([]);
}
log(ansi_colors_1.default.blue('[local]'), `${extension.name}: ${ansi_colors_1.default.cyan(controlState)}`, ansi_colors_1.default.green('✔︎'));
return event_stream_1.default.readArray([]);
}
}
function readControlFile() {
try {
return JSON.parse(fs_1.default.readFileSync(controlFilePath, 'utf8'));
}
catch (err) {
return {};
}
}
function writeControlFile(control) {
fs_1.default.mkdirSync(path_1.default.dirname(controlFilePath), { recursive: true });
fs_1.default.writeFileSync(controlFilePath, JSON.stringify(control, null, 2));
}
function getBuiltInExtensions() {
log('Synchronizing built-in extensions...');
log(`You can manage built-in extensions with the ${ansi_colors_1.default.cyan('--builtin')} flag`);
const control = readControlFile();
const streams = [];
for (const extension of [...builtInExtensions, ...webBuiltInExtensions]) {
const controlState = control[extension.name] || 'marketplace';
control[extension.name] = controlState;
streams.push(syncExtension(extension, controlState));
}
writeControlFile(control);
return new Promise((resolve, reject) => {
event_stream_1.default.merge(streams)
.on('error', reject)
.on('end', resolve);
});
}
if (require.main === module) {
getBuiltInExtensions().then(() => process.exit(0)).catch(err => {
console.error(err);
process.exit(1);
});
}
//# sourceMappingURL=builtInExtensions.js.map
================================================
FILE: build/lib/builtInExtensions.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import os from 'os';
import rimraf from 'rimraf';
import es from 'event-stream';
import rename from 'gulp-rename';
import vfs from 'vinyl-fs';
import * as ext from './extensions';
import fancyLog from 'fancy-log';
import ansiColors from 'ansi-colors';
import { Stream } from 'stream';
export interface IExtensionDefinition {
name: string;
version: string;
sha256: string;
repo: string;
platforms?: string[];
vsix?: string;
metadata: {
id: string;
publisherId: {
publisherId: string;
publisherName: string;
displayName: string;
flags: string;
};
publisherDisplayName: string;
};
}
const root = path.dirname(path.dirname(__dirname));
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = productjson.builtInExtensions || [];
const webBuiltInExtensions = productjson.webBuiltInExtensions || [];
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
const ENABLE_LOGGING = !process.env['VSCODE_BUILD_BUILTIN_EXTENSIONS_SILENCE_PLEASE'];
function log(...messages: string[]): void {
if (ENABLE_LOGGING) {
fancyLog(...messages);
}
}
function getExtensionPath(extension: IExtensionDefinition): string {
return path.join(root, '.build', 'builtInExtensions', extension.name);
}
function isUpToDate(extension: IExtensionDefinition): boolean {
const packagePath = path.join(getExtensionPath(extension), 'package.json');
if (!fs.existsSync(packagePath)) {
return false;
}
const packageContents = fs.readFileSync(packagePath, { encoding: 'utf8' });
try {
const diskVersion = JSON.parse(packageContents).version;
return (diskVersion === extension.version);
} catch (err) {
return false;
}
}
function getExtensionDownloadStream(extension: IExtensionDefinition) {
let input: Stream;
if (extension.vsix) {
input = ext.fromVsix(path.join(root, extension.vsix), extension);
} else if (productjson.extensionsGallery?.serviceUrl) {
input = ext.fromMarketplace(productjson.extensionsGallery.serviceUrl, extension);
} else {
input = ext.fromGithub(extension);
}
return input.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`));
}
export function getExtensionStream(extension: IExtensionDefinition) {
// if the extension exists on disk, use those files instead of downloading anew
if (isUpToDate(extension)) {
log('[extensions]', `${extension.name}@${extension.version} up to date`, ansiColors.green('✔︎'));
return vfs.src(['**'], { cwd: getExtensionPath(extension), dot: true })
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`));
}
return getExtensionDownloadStream(extension);
}
function syncMarketplaceExtension(extension: IExtensionDefinition): Stream {
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
const source = ansiColors.blue(galleryServiceUrl ? '[marketplace]' : '[github]');
if (isUpToDate(extension)) {
log(source, `${extension.name}@${extension.version}`, ansiColors.green('✔︎'));
return es.readArray([]);
}
rimraf.sync(getExtensionPath(extension));
return getExtensionDownloadStream(extension)
.pipe(vfs.dest('.build/builtInExtensions'))
.on('end', () => log(source, extension.name, ansiColors.green('✔︎')));
}
function syncExtension(extension: IExtensionDefinition, controlState: 'disabled' | 'marketplace'): Stream {
if (extension.platforms) {
const platforms = new Set(extension.platforms);
if (!platforms.has(process.platform)) {
log(ansiColors.gray('[skip]'), `${extension.name}@${extension.version}: Platform '${process.platform}' not supported: [${extension.platforms}]`, ansiColors.green('✔︎'));
return es.readArray([]);
}
}
switch (controlState) {
case 'disabled':
log(ansiColors.blue('[disabled]'), ansiColors.gray(extension.name));
return es.readArray([]);
case 'marketplace':
return syncMarketplaceExtension(extension);
default:
if (!fs.existsSync(controlState)) {
log(ansiColors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`));
return es.readArray([]);
} else if (!fs.existsSync(path.join(controlState, 'package.json'))) {
log(ansiColors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`));
return es.readArray([]);
}
log(ansiColors.blue('[local]'), `${extension.name}: ${ansiColors.cyan(controlState)}`, ansiColors.green('✔︎'));
return es.readArray([]);
}
}
interface IControlFile {
[name: string]: 'disabled' | 'marketplace';
}
function readControlFile(): IControlFile {
try {
return JSON.parse(fs.readFileSync(controlFilePath, 'utf8'));
} catch (err) {
return {};
}
}
function writeControlFile(control: IControlFile): void {
fs.mkdirSync(path.dirname(controlFilePath), { recursive: true });
fs.writeFileSync(controlFilePath, JSON.stringify(control, null, 2));
}
export function getBuiltInExtensions(): Promise {
log('Synchronizing built-in extensions...');
log(`You can manage built-in extensions with the ${ansiColors.cyan('--builtin')} flag`);
const control = readControlFile();
const streams: Stream[] = [];
for (const extension of [...builtInExtensions, ...webBuiltInExtensions]) {
const controlState = control[extension.name] || 'marketplace';
control[extension.name] = controlState;
streams.push(syncExtension(extension, controlState));
}
writeControlFile(control);
return new Promise((resolve, reject) => {
es.merge(streams)
.on('error', reject)
.on('end', resolve);
});
}
if (require.main === module) {
getBuiltInExtensions().then(() => process.exit(0)).catch(err => {
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/lib/builtInExtensionsCG.js
================================================
"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const url_1 = __importDefault(require("url"));
const ansi_colors_1 = __importDefault(require("ansi-colors"));
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
const rootCG = path_1.default.join(root, 'extensionsCG');
const productjson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = productjson.builtInExtensions || [];
const webBuiltInExtensions = productjson.webBuiltInExtensions || [];
const token = process.env['GITHUB_TOKEN'];
const contentBasePath = 'raw.githubusercontent.com';
const contentFileNames = ['package.json', 'package-lock.json'];
async function downloadExtensionDetails(extension) {
const extensionLabel = `${extension.name}@${extension.version}`;
const repository = url_1.default.parse(extension.repo).path.substr(1);
const repositoryContentBaseUrl = `https://${token ? `${token}@` : ''}${contentBasePath}/${repository}/v${extension.version}`;
async function getContent(fileName) {
try {
const response = await fetch(`${repositoryContentBaseUrl}/${fileName}`);
if (response.ok) {
return { fileName, body: Buffer.from(await response.arrayBuffer()) };
}
else if (response.status === 404) {
return { fileName, body: undefined };
}
else {
return { fileName, body: null };
}
}
catch (e) {
return { fileName, body: null };
}
}
const promises = contentFileNames.map(getContent);
console.log(extensionLabel);
const results = await Promise.all(promises);
for (const result of results) {
if (result.body) {
const extensionFolder = path_1.default.join(rootCG, extension.name);
fs_1.default.mkdirSync(extensionFolder, { recursive: true });
fs_1.default.writeFileSync(path_1.default.join(extensionFolder, result.fileName), result.body);
console.log(` - ${result.fileName} ${ansi_colors_1.default.green('✔︎')}`);
}
else if (result.body === undefined) {
console.log(` - ${result.fileName} ${ansi_colors_1.default.yellow('⚠️')}`);
}
else {
console.log(` - ${result.fileName} ${ansi_colors_1.default.red('🛑')}`);
}
}
// Validation
if (!results.find(r => r.fileName === 'package.json')?.body) {
// throw new Error(`The "package.json" file could not be found for the built-in extension - ${extensionLabel}`);
}
if (!results.find(r => r.fileName === 'package-lock.json')?.body) {
// throw new Error(`The "package-lock.json" could not be found for the built-in extension - ${extensionLabel}`);
}
}
async function main() {
for (const extension of [...builtInExtensions, ...webBuiltInExtensions]) {
await downloadExtensionDetails(extension);
}
}
main().then(() => {
console.log(`Built-in extensions component data downloaded ${ansi_colors_1.default.green('✔︎')}`);
process.exit(0);
}, err => {
console.log(`Built-in extensions component data could not be downloaded ${ansi_colors_1.default.red('🛑')}`);
console.error(err);
process.exit(1);
});
//# sourceMappingURL=builtInExtensionsCG.js.map
================================================
FILE: build/lib/builtInExtensionsCG.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import url from 'url';
import ansiColors from 'ansi-colors';
import { IExtensionDefinition } from './builtInExtensions';
const root = path.dirname(path.dirname(__dirname));
const rootCG = path.join(root, 'extensionsCG');
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = productjson.builtInExtensions || [];
const webBuiltInExtensions = productjson.webBuiltInExtensions || [];
const token = process.env['GITHUB_TOKEN'];
const contentBasePath = 'raw.githubusercontent.com';
const contentFileNames = ['package.json', 'package-lock.json'];
async function downloadExtensionDetails(extension: IExtensionDefinition): Promise {
const extensionLabel = `${extension.name}@${extension.version}`;
const repository = url.parse(extension.repo).path!.substr(1);
const repositoryContentBaseUrl = `https://${token ? `${token}@` : ''}${contentBasePath}/${repository}/v${extension.version}`;
async function getContent(fileName: string): Promise<{ fileName: string; body: Buffer | undefined | null }> {
try {
const response = await fetch(`${repositoryContentBaseUrl}/${fileName}`);
if (response.ok) {
return { fileName, body: Buffer.from(await response.arrayBuffer()) };
} else if (response.status === 404) {
return { fileName, body: undefined };
} else {
return { fileName, body: null };
}
} catch (e) {
return { fileName, body: null };
}
}
const promises = contentFileNames.map(getContent);
console.log(extensionLabel);
const results = await Promise.all(promises);
for (const result of results) {
if (result.body) {
const extensionFolder = path.join(rootCG, extension.name);
fs.mkdirSync(extensionFolder, { recursive: true });
fs.writeFileSync(path.join(extensionFolder, result.fileName), result.body);
console.log(` - ${result.fileName} ${ansiColors.green('✔︎')}`);
} else if (result.body === undefined) {
console.log(` - ${result.fileName} ${ansiColors.yellow('⚠️')}`);
} else {
console.log(` - ${result.fileName} ${ansiColors.red('🛑')}`);
}
}
// Validation
if (!results.find(r => r.fileName === 'package.json')?.body) {
// throw new Error(`The "package.json" file could not be found for the built-in extension - ${extensionLabel}`);
}
if (!results.find(r => r.fileName === 'package-lock.json')?.body) {
// throw new Error(`The "package-lock.json" could not be found for the built-in extension - ${extensionLabel}`);
}
}
async function main(): Promise {
for (const extension of [...builtInExtensions, ...webBuiltInExtensions]) {
await downloadExtensionDetails(extension);
}
}
main().then(() => {
console.log(`Built-in extensions component data downloaded ${ansiColors.green('✔︎')}`);
process.exit(0);
}, err => {
console.log(`Built-in extensions component data could not be downloaded ${ansiColors.red('🛑')}`);
console.error(err);
process.exit(1);
});
================================================
FILE: build/lib/bundle.js
================================================
"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) {
const seen = new Array(BOILERPLATE.length).fill(true, 0, BOILERPLATE.length);
return removeDuplicateTSBoilerplate(source, seen);
}
// Taken from typescript compiler => emitFiles
const BOILERPLATE = [
{ start: /^var __extends/, end: /^}\)\(\);$/ },
{ start: /^var __assign/, end: /^};$/ },
{ start: /^var __decorate/, end: /^};$/ },
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
{ start: /^var __generator/, end: /^};$/ },
{ start: /^var __createBinding/, end: /^}\)\);$/ },
{ start: /^var __setModuleDefault/, end: /^}\);$/ },
{ start: /^var __importStar/, end: /^};$/ },
{ start: /^var __addDisposableResource/, end: /^};$/ },
{ start: /^var __disposeResources/, end: /^}\);$/ },
];
function removeDuplicateTSBoilerplate(source, SEEN_BOILERPLATE = []) {
const lines = source.split(/\r\n|\n|\r/);
const newLines = [];
let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (IS_REMOVING_BOILERPLATE) {
newLines.push('');
if (END_BOILERPLATE.test(line)) {
IS_REMOVING_BOILERPLATE = false;
}
}
else {
for (let j = 0; j < BOILERPLATE.length; j++) {
const boilerplate = BOILERPLATE[j];
if (boilerplate.start.test(line)) {
if (SEEN_BOILERPLATE[j]) {
IS_REMOVING_BOILERPLATE = true;
END_BOILERPLATE = boilerplate.end;
}
else {
SEEN_BOILERPLATE[j] = true;
}
}
}
if (IS_REMOVING_BOILERPLATE) {
newLines.push('');
}
else {
newLines.push(line);
}
}
}
return newLines.join('\n');
}
//# sourceMappingURL=bundle.js.map
================================================
FILE: build/lib/bundle.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface IEntryPoint {
name: string;
include?: string[];
dest?: string;
}
export function removeAllTSBoilerplate(source: string) {
const seen = new Array(BOILERPLATE.length).fill(true, 0, BOILERPLATE.length);
return removeDuplicateTSBoilerplate(source, seen);
}
// Taken from typescript compiler => emitFiles
const BOILERPLATE = [
{ start: /^var __extends/, end: /^}\)\(\);$/ },
{ start: /^var __assign/, end: /^};$/ },
{ start: /^var __decorate/, end: /^};$/ },
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
{ start: /^var __generator/, end: /^};$/ },
{ start: /^var __createBinding/, end: /^}\)\);$/ },
{ start: /^var __setModuleDefault/, end: /^}\);$/ },
{ start: /^var __importStar/, end: /^};$/ },
{ start: /^var __addDisposableResource/, end: /^};$/ },
{ start: /^var __disposeResources/, end: /^}\);$/ },
];
function removeDuplicateTSBoilerplate(source: string, SEEN_BOILERPLATE: boolean[] = []): string {
const lines = source.split(/\r\n|\n|\r/);
const newLines: string[] = [];
let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE: RegExp;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (IS_REMOVING_BOILERPLATE) {
newLines.push('');
if (END_BOILERPLATE!.test(line)) {
IS_REMOVING_BOILERPLATE = false;
}
} else {
for (let j = 0; j < BOILERPLATE.length; j++) {
const boilerplate = BOILERPLATE[j];
if (boilerplate.start.test(line)) {
if (SEEN_BOILERPLATE[j]) {
IS_REMOVING_BOILERPLATE = true;
END_BOILERPLATE = boilerplate.end;
} else {
SEEN_BOILERPLATE[j] = true;
}
}
}
if (IS_REMOVING_BOILERPLATE) {
newLines.push('');
} else {
newLines.push(line);
}
}
}
return newLines.join('\n');
}
================================================
FILE: build/lib/compilation.js
================================================
"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 });
exports.watchApiProposalNamesTask = exports.compileApiProposalNamesTask = void 0;
exports.createCompile = createCompile;
exports.transpileTask = transpileTask;
exports.compileTask = compileTask;
exports.watchTask = watchTask;
const event_stream_1 = __importDefault(require("event-stream"));
const fs_1 = __importDefault(require("fs"));
const gulp_1 = __importDefault(require("gulp"));
const path_1 = __importDefault(require("path"));
const monacodts = __importStar(require("./monaco-api"));
const nls = __importStar(require("./nls"));
const reporter_1 = require("./reporter");
const util = __importStar(require("./util"));
const fancy_log_1 = __importDefault(require("fancy-log"));
const ansi_colors_1 = __importDefault(require("ansi-colors"));
const os_1 = __importDefault(require("os"));
const vinyl_1 = __importDefault(require("vinyl"));
const task = __importStar(require("./task"));
const index_1 = require("./mangle/index");
const postcss_1 = require("./postcss");
const ts = require("typescript");
const watch = require('./watch');
// --- gulp-tsb: compile and transpile --------------------------------
const reporter = (0, reporter_1.createReporter)();
function getTypeScriptCompilerOptions(src) {
const rootDir = path_1.default.join(__dirname, `../../${src}`);
const options = {};
options.verbose = false;
options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
options.sourceMap = false;
}
options.rootDir = rootDir;
options.baseUrl = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs_1.default.readFileSync(__filename, 'utf8')) ? 0 : 1;
return options;
}
function createCompile(src, { build, emitError, transpileOnly, preserveEnglish }) {
const tsb = require('./tsb');
const sourcemaps = require('gulp-sourcemaps');
const projectPath = path_1.default.join(__dirname, '../../', src, 'tsconfig.json');
const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) };
if (!build) {
overrideOptions.inlineSourceMap = true;
}
const compilation = tsb.create(projectPath, overrideOptions, {
verbose: false,
transpileOnly: Boolean(transpileOnly),
transpileWithSwc: 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 isCSS = (f) => f.path.endsWith('.css') && !f.path.includes('fixtures');
const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path)));
const postcssNesting = require('postcss-nesting');
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(!build && isRuntimeJs, util.appendOwnPathSourceURL()))
.pipe(util.$if(isCSS, (0, postcss_1.gulpPostcss)([postcssNesting()], err => reporter(String(err)))))
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(compilation(token))
.pipe(noDeclarationsFilter)
.pipe(util.$if(build, nls.nls({ preserveEnglish })))
.pipe(noDeclarationsFilter.restore)
.pipe(util.$if(!transpileOnly, sourcemaps.write('.', {
addComment: false,
includeContent: !!build,
sourceRoot: overrideOptions.sourceRoot
})))
.pipe(tsFilter.restore)
.pipe(reporter.end(!!emitError));
return event_stream_1.default.duplex(input, output);
}
pipeline.tsProjectSrc = () => {
return compilation.src({ base: src });
};
pipeline.projectPath = projectPath;
return pipeline;
}
function transpileTask(src, out, esbuild) {
const task = () => {
const transpile = createCompile(src, { build: false, emitError: true, transpileOnly: { esbuild }, preserveEnglish: false });
const srcPipe = gulp_1.default.src(`${src}/**`, { base: `${src}` });
return srcPipe
.pipe(transpile())
.pipe(gulp_1.default.dest(out));
};
task.taskName = `transpile-${path_1.default.basename(src)}`;
return task;
}
function compileTask(src, out, build, options = {}) {
const task = () => {
if (os_1.default.totalmem() < 4_000_000_000) {
throw new Error('compilation requires 4GB of RAM');
}
const compile = createCompile(src, { build, emitError: true, transpileOnly: false, preserveEnglish: !!options.preserveEnglish });
const srcPipe = gulp_1.default.src(`${src}/**`, { base: `${src}` });
const generator = new MonacoGenerator(false);
if (src === 'src') {
generator.execute();
}
// mangle: TypeScript to TypeScript
let mangleStream = event_stream_1.default.through();
if (build && !options.disableMangle) {
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 newContents = (await newContentsByFileName).get(tsNormalPath);
if (newContents !== undefined) {
data.contents = Buffer.from(newContents.out);
data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap);
}
this.push(data);
}, async function end() {
// free resources
(await newContentsByFileName).clear();
this.push(null);
ts2tsMangler = undefined;
});
}
return srcPipe
.pipe(mangleStream)
.pipe(generator.stream)
.pipe(compile())
.pipe(gulp_1.default.dest(out));
};
task.taskName = `compile-${path_1.default.basename(src)}`;
return task;
}
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 generator = new MonacoGenerator(true);
generator.execute();
return watchSrc
.pipe(generator.stream)
.pipe(util.incremental(compile, src, true))
.pipe(gulp_1.default.dest(out));
};
task.taskName = `watch-${path_1.default.basename(out)}`;
return task;
}
const REPO_SRC_FOLDER = path_1.default.join(__dirname, '../../src');
class MonacoGenerator {
_isWatch;
stream;
_watchedFiles;
_fsProvider;
_declarationResolver;
constructor(isWatch) {
this._isWatch = isWatch;
this.stream = event_stream_1.default.through();
this._watchedFiles = {};
const onWillReadFile = (moduleId, filePath) => {
if (!this._isWatch) {
return;
}
if (this._watchedFiles[filePath]) {
return;
}
this._watchedFiles[filePath] = true;
fs_1.default.watchFile(filePath, () => {
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
};
this._fsProvider = new class extends monacodts.FSProvider {
readFileSync(moduleId, filePath) {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
fs_1.default.watchFile(monacodts.RECIPE_PATH, () => {
this._executeSoon();
});
}
}
_executeSoonTimer = null;
_executeSoon() {
if (this._executeSoonTimer !== null) {
clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
this.execute();
}, 20);
}
_run() {
const r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
_log(message, ...rest) {
(0, fancy_log_1.default)(ansi_colors_1.default.cyan('[monaco.d.ts]'), message, ...rest);
}
execute() {
const startTime = Date.now();
const result = this._run();
if (!result) {
// nothing really changed
return;
}
if (result.isTheSame) {
return;
}
fs_1.default.writeFileSync(result.filePath, result.content);
fs_1.default.writeFileSync(path_1.default.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`);
if (!this._isWatch) {
this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
}
}
}
function generateApiProposalNames() {
let eol;
try {
const src = fs_1.default.readFileSync('src/vs/platform/extensions/common/extensionsApiProposals.ts', 'utf-8');
const match = /\r?\n/m.exec(src);
eol = match ? match[0] : os_1.default.EOL;
}
catch {
eol = os_1.default.EOL;
}
const pattern = /vscode\.proposed\.([a-zA-Z\d]+)\.d\.ts$/;
const versionPattern = /^\s*\/\/\s*version\s*:\s*(\d+)\s*$/mi;
const proposals = new Map();
const input = event_stream_1.default.through();
const output = input
.pipe(util.filter((f) => pattern.test(f.path)))
.pipe(event_stream_1.default.through((f) => {
const name = path_1.default.basename(f.path);
const match = pattern.exec(name);
if (!match) {
return;
}
const proposalName = match[1];
const contents = f.contents.toString('utf8');
const versionMatch = versionPattern.exec(contents);
const version = versionMatch ? versionMatch[1] : undefined;
proposals.set(proposalName, {
proposal: `https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.${proposalName}.d.ts`,
version: version ? parseInt(version) : undefined
});
}, function () {
const names = [...proposals.keys()].sort();
const contents = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the MIT License. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/',
'',
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
'',
'const _allApiProposals = {',
`${names.map(proposalName => {
const proposal = proposals.get(proposalName);
return `\t${proposalName}: {${eol}\t\tproposal: '${proposal.proposal}',${eol}${proposal.version ? `\t\tversion: ${proposal.version}${eol}` : ''}\t}`;
}).join(`,${eol}`)}`,
'};',
'export const allApiProposals = Object.freeze<{ [proposalName: string]: Readonly<{ proposal: string; version?: number }> }>(_allApiProposals);',
'export type ApiProposalName = keyof typeof _allApiProposals;',
'',
].join(eol);
this.emit('data', new vinyl_1.default({
path: 'vs/platform/extensions/common/extensionsApiProposals.ts',
contents: Buffer.from(contents)
}));
this.emit('end');
}));
return event_stream_1.default.duplex(input, output);
}
const apiProposalNamesReporter = (0, reporter_1.createReporter)('api-proposal-names');
exports.compileApiProposalNamesTask = task.define('compile-api-proposal-names', () => {
return gulp_1.default.src('src/vscode-dts/**')
.pipe(generateApiProposalNames())
.pipe(gulp_1.default.dest('src'))
.pipe(apiProposalNamesReporter.end(true));
});
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 })
.pipe(util.debounce(task))
.pipe(gulp_1.default.dest('src'));
});
//# sourceMappingURL=compilation.js.map
================================================
FILE: build/lib/compilation.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import es from 'event-stream';
import fs from 'fs';
import gulp from 'gulp';
import path from 'path';
import * as monacodts from './monaco-api';
import * as nls from './nls';
import { createReporter } from './reporter';
import * as util from './util';
import fancyLog from 'fancy-log';
import ansiColors from 'ansi-colors';
import os from 'os';
import File from 'vinyl';
import * as task from './task';
import { Mangler } from './mangle/index';
import { RawSourceMap } from 'source-map';
import { gulpPostcss } from './postcss';
import ts = require('typescript');
const watch = require('./watch');
// --- gulp-tsb: compile and transpile --------------------------------
const reporter = createReporter();
function getTypeScriptCompilerOptions(src: string): ts.CompilerOptions {
const rootDir = path.join(__dirname, `../../${src}`);
const options: ts.CompilerOptions = {};
options.verbose = false;
options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
options.sourceMap = false;
}
options.rootDir = rootDir;
options.baseUrl = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 0 : 1;
return options;
}
interface ICompileTaskOptions {
readonly build: boolean;
readonly emitError: boolean;
readonly transpileOnly: boolean | { esbuild: boolean };
readonly preserveEnglish: boolean;
}
export function createCompile(src: string, { build, emitError, transpileOnly, preserveEnglish }: ICompileTaskOptions) {
const tsb = require('./tsb') as typeof import('./tsb');
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) };
if (!build) {
overrideOptions.inlineSourceMap = true;
}
const compilation = tsb.create(projectPath, overrideOptions, {
verbose: false,
transpileOnly: Boolean(transpileOnly),
transpileWithSwc: typeof transpileOnly !== 'boolean' && transpileOnly.esbuild
}, 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);
const isRuntimeJs = (f: File) => f.path.endsWith('.js') && !f.path.includes('fixtures');
const isCSS = (f: File) => f.path.endsWith('.css') && !f.path.includes('fixtures');
const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path)));
const postcssNesting = require('postcss-nesting');
const input = es.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(!build && isRuntimeJs, util.appendOwnPathSourceURL()))
.pipe(util.$if(isCSS, gulpPostcss([postcssNesting()], err => reporter(String(err)))))
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(compilation(token))
.pipe(noDeclarationsFilter)
.pipe(util.$if(build, nls.nls({ preserveEnglish })))
.pipe(noDeclarationsFilter.restore)
.pipe(util.$if(!transpileOnly, sourcemaps.write('.', {
addComment: false,
includeContent: !!build,
sourceRoot: overrideOptions.sourceRoot
})))
.pipe(tsFilter.restore)
.pipe(reporter.end(!!emitError));
return es.duplex(input, output);
}
pipeline.tsProjectSrc = () => {
return compilation.src({ base: src });
};
pipeline.projectPath = projectPath;
return pipeline;
}
export function transpileTask(src: string, out: string, esbuild: boolean): task.StreamTask {
const task = () => {
const transpile = createCompile(src, { build: false, emitError: true, transpileOnly: { esbuild }, preserveEnglish: false });
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
return srcPipe
.pipe(transpile())
.pipe(gulp.dest(out));
};
task.taskName = `transpile-${path.basename(src)}`;
return task;
}
export function compileTask(src: string, out: string, build: boolean, options: { disableMangle?: boolean; preserveEnglish?: boolean } = {}): task.StreamTask {
const task = () => {
if (os.totalmem() < 4_000_000_000) {
throw new Error('compilation requires 4GB of RAM');
}
const compile = createCompile(src, { build, emitError: true, transpileOnly: false, preserveEnglish: !!options.preserveEnglish });
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
const generator = new MonacoGenerator(false);
if (src === 'src') {
generator.execute();
}
// mangle: TypeScript to TypeScript
let mangleStream = es.through();
if (build && !options.disableMangle) {
let ts2tsMangler = new Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data), { mangleExports: true, manglePrivateFields: true });
const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState']));
mangleStream = es.through(async function write(data: File & { sourceMap?: RawSourceMap }) {
type TypeScriptExt = typeof ts & { normalizePath(path: string): string };
const tsNormalPath = (ts).normalizePath(data.path);
const newContents = (await newContentsByFileName).get(tsNormalPath);
if (newContents !== undefined) {
data.contents = Buffer.from(newContents.out);
data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap);
}
this.push(data);
}, async function end() {
// free resources
(await newContentsByFileName).clear();
this.push(null);
(ts2tsMangler) = undefined;
});
}
return srcPipe
.pipe(mangleStream)
.pipe(generator.stream)
.pipe(compile())
.pipe(gulp.dest(out));
};
task.taskName = `compile-${path.basename(src)}`;
return task;
}
export function watchTask(out: string, build: boolean, srcPath: string = 'src'): task.StreamTask {
const task = () => {
const compile = createCompile(srcPath, { build, emitError: false, transpileOnly: false, preserveEnglish: false });
const src = gulp.src(`${srcPath}/**`, { base: srcPath });
const watchSrc = watch(`${srcPath}/**`, { base: srcPath, readDelay: 200 });
const generator = new MonacoGenerator(true);
generator.execute();
return watchSrc
.pipe(generator.stream)
.pipe(util.incremental(compile, src, true))
.pipe(gulp.dest(out));
};
task.taskName = `watch-${path.basename(out)}`;
return task;
}
const REPO_SRC_FOLDER = path.join(__dirname, '../../src');
class MonacoGenerator {
private readonly _isWatch: boolean;
public readonly stream: NodeJS.ReadWriteStream;
private readonly _watchedFiles: { [filePath: string]: boolean };
private readonly _fsProvider: monacodts.FSProvider;
private readonly _declarationResolver: monacodts.DeclarationResolver;
constructor(isWatch: boolean) {
this._isWatch = isWatch;
this.stream = es.through();
this._watchedFiles = {};
const onWillReadFile = (moduleId: string, filePath: string) => {
if (!this._isWatch) {
return;
}
if (this._watchedFiles[filePath]) {
return;
}
this._watchedFiles[filePath] = true;
fs.watchFile(filePath, () => {
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
};
this._fsProvider = new class extends monacodts.FSProvider {
public readFileSync(moduleId: string, filePath: string): Buffer {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
fs.watchFile(monacodts.RECIPE_PATH, () => {
this._executeSoon();
});
}
}
private _executeSoonTimer: NodeJS.Timeout | null = null;
private _executeSoon(): void {
if (this._executeSoonTimer !== null) {
clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
this.execute();
}, 20);
}
private _run(): monacodts.IMonacoDeclarationResult | null {
const r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
private _log(message: any, ...rest: any[]): void {
fancyLog(ansiColors.cyan('[monaco.d.ts]'), message, ...rest);
}
public execute(): void {
const startTime = Date.now();
const result = this._run();
if (!result) {
// nothing really changed
return;
}
if (result.isTheSame) {
return;
}
fs.writeFileSync(result.filePath, result.content);
fs.writeFileSync(path.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`);
if (!this._isWatch) {
this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
}
}
}
function generateApiProposalNames() {
let eol: string;
try {
const src = fs.readFileSync('src/vs/platform/extensions/common/extensionsApiProposals.ts', 'utf-8');
const match = /\r?\n/m.exec(src);
eol = match ? match[0] : os.EOL;
} catch {
eol = os.EOL;
}
const pattern = /vscode\.proposed\.([a-zA-Z\d]+)\.d\.ts$/;
const versionPattern = /^\s*\/\/\s*version\s*:\s*(\d+)\s*$/mi;
const proposals = new Map();
const input = es.through();
const output = input
.pipe(util.filter((f: File) => pattern.test(f.path)))
.pipe(es.through((f: File) => {
const name = path.basename(f.path);
const match = pattern.exec(name);
if (!match) {
return;
}
const proposalName = match[1];
const contents = f.contents.toString('utf8');
const versionMatch = versionPattern.exec(contents);
const version = versionMatch ? versionMatch[1] : undefined;
proposals.set(proposalName, {
proposal: `https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.${proposalName}.d.ts`,
version: version ? parseInt(version) : undefined
});
}, function () {
const names = [...proposals.keys()].sort();
const contents = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the MIT License. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/',
'',
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
'',
'const _allApiProposals = {',
`${names.map(proposalName => {
const proposal = proposals.get(proposalName)!;
return `\t${proposalName}: {${eol}\t\tproposal: '${proposal.proposal}',${eol}${proposal.version ? `\t\tversion: ${proposal.version}${eol}` : ''}\t}`;
}).join(`,${eol}`)}`,
'};',
'export const allApiProposals = Object.freeze<{ [proposalName: string]: Readonly<{ proposal: string; version?: number }> }>(_allApiProposals);',
'export type ApiProposalName = keyof typeof _allApiProposals;',
'',
].join(eol);
this.emit('data', new File({
path: 'vs/platform/extensions/common/extensionsApiProposals.ts',
contents: Buffer.from(contents)
}));
this.emit('end');
}));
return es.duplex(input, output);
}
const apiProposalNamesReporter = createReporter('api-proposal-names');
export const compileApiProposalNamesTask = task.define('compile-api-proposal-names', () => {
return gulp.src('src/vscode-dts/**')
.pipe(generateApiProposalNames())
.pipe(gulp.dest('src'))
.pipe(apiProposalNamesReporter.end(true));
});
export const watchApiProposalNamesTask = task.define('watch-api-proposal-names', () => {
const task = () => gulp.src('src/vscode-dts/**')
.pipe(generateApiProposalNames())
.pipe(apiProposalNamesReporter.end(true));
return watch('src/vscode-dts/**', { readDelay: 200 })
.pipe(util.debounce(task))
.pipe(gulp.dest('src'));
});
================================================
FILE: build/lib/date.js
================================================
"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;
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const root = path_1.default.join(__dirname, '..', '..');
/**
* Writes a `outDir/date` file with the contents of the build
* so that other tasks during the build process can use it and
* all use the same date.
*/
function writeISODate(outDir) {
const result = () => new Promise((resolve, _) => {
const outDirectory = path_1.default.join(root, outDir);
fs_1.default.mkdirSync(outDirectory, { recursive: true });
const date = new Date().toISOString();
fs_1.default.writeFileSync(path_1.default.join(outDirectory, 'date'), date, 'utf8');
resolve();
});
result.taskName = 'build-date-file';
return result;
}
function readISODate(outDir) {
const outDirectory = path_1.default.join(root, outDir);
return fs_1.default.readFileSync(path_1.default.join(outDirectory, 'date'), 'utf8');
}
//# sourceMappingURL=date.js.map
================================================
FILE: build/lib/date.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import path from 'path';
import fs from 'fs';
const root = path.join(__dirname, '..', '..');
/**
* Writes a `outDir/date` file with the contents of the build
* so that other tasks during the build process can use it and
* all use the same date.
*/
export function writeISODate(outDir: string) {
const result = () => new Promise((resolve, _) => {
const outDirectory = path.join(root, outDir);
fs.mkdirSync(outDirectory, { recursive: true });
const date = new Date().toISOString();
fs.writeFileSync(path.join(outDirectory, 'date'), date, 'utf8');
resolve();
});
result.taskName = 'build-date-file';
return result;
}
export function readISODate(outDir: string): string {
const outDirectory = path.join(root, outDir);
return fs.readFileSync(path.join(outDirectory, 'date'), 'utf8');
}
================================================
FILE: build/lib/dependencies.js
================================================
"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;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const child_process_1 = __importDefault(require("child_process"));
const root = fs_1.default.realpathSync(path_1.default.dirname(path_1.default.dirname(__dirname)));
function getNpmProductionDependencies(folder) {
let raw;
try {
raw = child_process_1.default.execSync('npm ls --all --omit=dev --parseable', { cwd: folder, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, null] });
}
catch (err) {
const regex = /^npm ERR! .*$/gm;
let match;
while (match = regex.exec(err.message)) {
if (/ELSPROBLEMS/.test(match[0])) {
continue;
}
else if (/invalid: xterm/.test(match[0])) {
continue;
}
else if (/A complete log of this run/.test(match[0])) {
continue;
}
else {
throw err;
}
}
raw = err.stdout;
}
return raw.split(/\r?\n/).filter(line => {
return !!line.trim() && path_1.default.relative(root, line) !== path_1.default.relative(root, folder);
});
}
function getProductionDependencies(folderPath) {
const result = getNpmProductionDependencies(folderPath);
// Account for distro npm dependencies
const realFolderPath = fs_1.default.realpathSync(folderPath);
const relativeFolderPath = path_1.default.relative(root, realFolderPath);
const distroFolderPath = `${root}/.build/distro/npm/${relativeFolderPath}`;
if (fs_1.default.existsSync(distroFolderPath)) {
result.push(...getNpmProductionDependencies(distroFolderPath));
}
return [...new Set(result)];
}
if (require.main === module) {
console.log(JSON.stringify(getProductionDependencies(root), null, ' '));
}
//# sourceMappingURL=dependencies.js.map
================================================
FILE: build/lib/dependencies.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import cp from 'child_process';
const root = fs.realpathSync(path.dirname(path.dirname(__dirname)));
function getNpmProductionDependencies(folder: string): string[] {
let raw: string;
try {
raw = cp.execSync('npm ls --all --omit=dev --parseable', { cwd: folder, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, null] });
} catch (err) {
const regex = /^npm ERR! .*$/gm;
let match: RegExpExecArray | null;
while (match = regex.exec(err.message)) {
if (/ELSPROBLEMS/.test(match[0])) {
continue;
} else if (/invalid: xterm/.test(match[0])) {
continue;
} else if (/A complete log of this run/.test(match[0])) {
continue;
} else {
throw err;
}
}
raw = err.stdout;
}
return raw.split(/\r?\n/).filter(line => {
return !!line.trim() && path.relative(root, line) !== path.relative(root, folder);
});
}
export function getProductionDependencies(folderPath: string): string[] {
const result = getNpmProductionDependencies(folderPath);
// Account for distro npm dependencies
const realFolderPath = fs.realpathSync(folderPath);
const relativeFolderPath = path.relative(root, realFolderPath);
const distroFolderPath = `${root}/.build/distro/npm/${relativeFolderPath}`;
if (fs.existsSync(distroFolderPath)) {
result.push(...getNpmProductionDependencies(distroFolderPath));
}
return [...new Set(result)];
}
if (require.main === module) {
console.log(JSON.stringify(getProductionDependencies(root), null, ' '));
}
================================================
FILE: build/lib/electron.js
================================================
"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 });
exports.config = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const vinyl_fs_1 = __importDefault(require("vinyl-fs"));
const gulp_filter_1 = __importDefault(require("gulp-filter"));
const util = __importStar(require("./util"));
const getVersion_1 = require("./getVersion");
function isDocumentSuffix(str) {
return str === 'document' || str === 'script' || str === 'file' || str === 'source code';
}
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
const product = JSON.parse(fs_1.default.readFileSync(path_1.default.join(root, 'product.json'), 'utf8'));
const commit = (0, getVersion_1.getVersion)(root);
function createTemplate(input) {
return (params) => {
return input.replace(/<%=\s*([^\s]+)\s*%>/g, (match, key) => {
return params[key] || match;
});
};
}
const darwinCreditsTemplate = product.darwinCredits && createTemplate(fs_1.default.readFileSync(path_1.default.join(root, product.darwinCredits), 'utf8'));
/**
* Generate a `DarwinDocumentType` given a list of file extensions, an icon name, and an optional suffix or file type name.
* @param extensions A list of file extensions, such as `['bat', 'cmd']`
* @param icon A sentence-cased file type name that matches the lowercase name of a darwin icon resource.
* For example, `'HTML'` instead of `'html'`, or `'Java'` instead of `'java'`.
* This parameter is lowercased before it is used to reference an icon file.
* @param nameOrSuffix An optional suffix or a string to use as the file type. If a suffix is provided,
* it is used with the icon parameter to generate a file type string. If nothing is provided,
* `'document'` is used with the icon parameter to generate file type string.
*
* For example, if you call `darwinBundleDocumentType(..., 'HTML')`, the resulting file type is `"HTML document"`,
* and the `'html'` darwin icon is used.
*
* If you call `darwinBundleDocumentType(..., 'Javascript', 'file')`, the resulting file type is `"Javascript file"`.
* and the `'javascript'` darwin icon is used.
*
* If you call `darwinBundleDocumentType(..., 'bat', 'Windows command script')`, the file type is `"Windows command script"`,
* and the `'bat'` darwin icon is used.
*/
function darwinBundleDocumentType(extensions, icon, nameOrSuffix, utis) {
// If given a suffix, generate a name from it. If not given anything, default to 'document'
if (isDocumentSuffix(nameOrSuffix) || !nameOrSuffix) {
nameOrSuffix = icon.charAt(0).toUpperCase() + icon.slice(1) + ' ' + (nameOrSuffix ?? 'document');
}
return {
name: nameOrSuffix,
role: 'Editor',
ostypes: ['TEXT', 'utxt', 'TUTX', '****'],
extensions,
iconFile: 'resources/darwin/' + icon.toLowerCase() + '.icns',
utis
};
}
/**
* Generate several `DarwinDocumentType`s with unique names and a shared icon.
* @param types A map of file type names to their associated file extensions.
* @param icon A darwin icon resource to use. For example, `'HTML'` would refer to `resources/darwin/html.icns`
*
* Examples:
* ```
* darwinBundleDocumentTypes({ 'C header file': 'h', 'C source code': 'c' },'c')
* darwinBundleDocumentTypes({ 'React source code': ['jsx', 'tsx'] }, 'react')
* ```
*/
function darwinBundleDocumentTypes(types, icon) {
return Object.keys(types).map((name) => {
const extensions = types[name];
return {
name,
role: 'Editor',
ostypes: ['TEXT', 'utxt', 'TUTX', '****'],
extensions: Array.isArray(extensions) ? extensions : [extensions],
iconFile: 'resources/darwin/' + icon + '.icns'
};
});
}
const { electronVersion, msBuildId } = util.getElectronVersion();
exports.config = {
version: electronVersion,
tag: product.electronRepository ? `v${electronVersion}-${msBuildId}` : undefined,
productAppName: product.nameLong,
companyName: 'Microsoft Corporation',
copyright: 'Copyright (C) 2024 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools',
darwinHelpBookFolder: 'VS Code HelpBook',
darwinHelpBookName: 'VS Code HelpBook',
darwinBundleDocumentTypes: [
...darwinBundleDocumentTypes({ 'C header file': 'h', 'C source code': 'c' }, 'c'),
...darwinBundleDocumentTypes({ 'Git configuration file': ['gitattributes', 'gitconfig', 'gitignore'] }, 'config'),
...darwinBundleDocumentTypes({ 'HTML template document': ['asp', 'aspx', 'cshtml', 'jshtm', 'jsp', 'phtml', 'shtml'] }, 'html'),
darwinBundleDocumentType(['bat', 'cmd'], 'bat', 'Windows command script'),
darwinBundleDocumentType(['bowerrc'], 'Bower'),
darwinBundleDocumentType(['config', 'editorconfig', 'ini', 'cfg'], 'config', 'Configuration file'),
darwinBundleDocumentType(['hh', 'hpp', 'hxx', 'h++'], 'cpp', 'C++ header file'),
darwinBundleDocumentType(['cc', 'cpp', 'cxx', 'c++'], 'cpp', 'C++ source code'),
darwinBundleDocumentType(['m'], 'default', 'Objective-C source code'),
darwinBundleDocumentType(['mm'], 'cpp', 'Objective-C++ source code'),
darwinBundleDocumentType(['cs', 'csx'], 'csharp', 'C# source code'),
darwinBundleDocumentType(['css'], 'css', 'CSS'),
darwinBundleDocumentType(['go'], 'go', 'Go source code'),
darwinBundleDocumentType(['htm', 'html', 'xhtml'], 'HTML'),
darwinBundleDocumentType(['jade'], 'Jade'),
darwinBundleDocumentType(['jav', 'java'], 'Java'),
darwinBundleDocumentType(['js', 'jscsrc', 'jshintrc', 'mjs', 'cjs'], 'Javascript', 'file'),
darwinBundleDocumentType(['json'], 'JSON'),
darwinBundleDocumentType(['less'], 'Less'),
darwinBundleDocumentType(['markdown', 'md', 'mdoc', 'mdown', 'mdtext', 'mdtxt', 'mdwn', 'mkd', 'mkdn'], 'Markdown'),
darwinBundleDocumentType(['php'], 'PHP', 'source code'),
darwinBundleDocumentType(['ps1', 'psd1', 'psm1'], 'Powershell', 'script'),
darwinBundleDocumentType(['py', 'pyi'], 'Python', 'script'),
darwinBundleDocumentType(['gemspec', 'rb', 'erb'], 'Ruby', 'source code'),
darwinBundleDocumentType(['scss', 'sass'], 'SASS', 'file'),
darwinBundleDocumentType(['sql'], 'SQL', 'script'),
darwinBundleDocumentType(['ts'], 'TypeScript', 'file'),
darwinBundleDocumentType(['tsx', 'jsx'], 'React', 'source code'),
darwinBundleDocumentType(['vue'], 'Vue', 'source code'),
darwinBundleDocumentType(['ascx', 'csproj', 'dtd', 'plist', 'wxi', 'wxl', 'wxs', 'xml', 'xaml'], 'XML'),
darwinBundleDocumentType(['eyaml', 'eyml', 'yaml', 'yml'], 'YAML'),
darwinBundleDocumentType([
'bash', 'bash_login', 'bash_logout', 'bash_profile', 'bashrc',
'profile', 'rhistory', 'rprofile', 'sh', 'zlogin', 'zlogout',
'zprofile', 'zsh', 'zshenv', 'zshrc'
], 'Shell', 'script'),
// Default icon with specified names
...darwinBundleDocumentTypes({
'Clojure source code': ['clj', 'cljs', 'cljx', 'clojure'],
'VS Code workspace file': 'code-workspace',
'CoffeeScript source code': 'coffee',
'Comma Separated Values': 'csv',
'CMake script': 'cmake',
'Dart script': 'dart',
'Diff file': 'diff',
'Dockerfile': 'dockerfile',
'Gradle file': 'gradle',
'Groovy script': 'groovy',
'Makefile': ['makefile', 'mk'],
'Lua script': 'lua',
'Pug document': 'pug',
'Jupyter': 'ipynb',
'Lockfile': 'lock',
'Log file': 'log',
'Plain Text File': 'txt',
'Xcode project file': 'xcodeproj',
'Xcode workspace file': 'xcworkspace',
'Visual Basic script': 'vb',
'R source code': 'r',
'Rust source code': 'rs',
'Restructured Text document': 'rst',
'LaTeX document': ['tex', 'cls'],
'F# source code': 'fs',
'F# signature file': 'fsi',
'F# script': ['fsx', 'fsscript'],
'SVG document': ['svg'],
'TOML document': 'toml',
'Swift source code': 'swift',
}, 'default'),
// Default icon with default name
darwinBundleDocumentType([
'containerfile', 'ctp', 'dot', 'edn', 'handlebars', 'hbs', 'ml', 'mli',
'pl', 'pl6', 'pm', 'pm6', 'pod', 'pp', 'properties', 'psgi', 'rt', 't'
], 'default', product.nameLong + ' document'),
// Folder support ()
darwinBundleDocumentType([], 'default', 'Folder', ['public.folder'])
],
darwinBundleURLTypes: [{
role: 'Viewer',
name: product.nameLong,
urlSchemes: [product.urlProtocol]
}],
darwinForceDarkModeSupport: true,
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : undefined,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['GITHUB_TOKEN'],
repo: product.electronRepository || undefined,
validateChecksum: true,
checksumFile: path_1.default.join(root, 'build', 'checksums', 'electron.txt'),
};
function getElectron(arch) {
return () => {
const electron = require('@vscode/gulp-electron');
const json = require('gulp-json-editor');
const electronOpts = {
...exports.config,
platform: process.platform,
arch: arch === 'armhf' ? 'arm' : arch,
ffmpegChromium: false,
keepDefaultApp: true
};
return vinyl_fs_1.default.src('package.json')
.pipe(json({ name: product.nameShort }))
.pipe(electron(electronOpts))
.pipe((0, gulp_filter_1.default)(['**', '!**/app/package.json']))
.pipe(vinyl_fs_1.default.dest('.build/electron'));
};
}
async function main(arch = process.arch) {
const version = electronVersion;
const electronPath = path_1.default.join(root, '.build', 'electron');
const versionFile = path_1.default.join(electronPath, 'version');
const isUpToDate = fs_1.default.existsSync(versionFile) && fs_1.default.readFileSync(versionFile, 'utf8') === `${version}`;
if (!isUpToDate) {
await util.rimraf(electronPath)();
await util.streamToPromise(getElectron(arch)());
}
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}
//# sourceMappingURL=electron.js.map
================================================
FILE: build/lib/electron.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import vfs from 'vinyl-fs';
import filter from 'gulp-filter';
import * as util from './util';
import { getVersion } from './getVersion';
type DarwinDocumentSuffix = 'document' | 'script' | 'file' | 'source code';
type DarwinDocumentType = {
name: string;
role: string;
ostypes: string[];
extensions: string[];
iconFile: string;
utis?: string[];
};
function isDocumentSuffix(str?: string): str is DarwinDocumentSuffix {
return str === 'document' || str === 'script' || str === 'file' || str === 'source code';
}
const root = path.dirname(path.dirname(__dirname));
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
const commit = getVersion(root);
function createTemplate(input: string): (params: Record) => string {
return (params: Record) => {
return input.replace(/<%=\s*([^\s]+)\s*%>/g, (match, key) => {
return params[key] || match;
});
};
}
const darwinCreditsTemplate = product.darwinCredits && createTemplate(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
/**
* Generate a `DarwinDocumentType` given a list of file extensions, an icon name, and an optional suffix or file type name.
* @param extensions A list of file extensions, such as `['bat', 'cmd']`
* @param icon A sentence-cased file type name that matches the lowercase name of a darwin icon resource.
* For example, `'HTML'` instead of `'html'`, or `'Java'` instead of `'java'`.
* This parameter is lowercased before it is used to reference an icon file.
* @param nameOrSuffix An optional suffix or a string to use as the file type. If a suffix is provided,
* it is used with the icon parameter to generate a file type string. If nothing is provided,
* `'document'` is used with the icon parameter to generate file type string.
*
* For example, if you call `darwinBundleDocumentType(..., 'HTML')`, the resulting file type is `"HTML document"`,
* and the `'html'` darwin icon is used.
*
* If you call `darwinBundleDocumentType(..., 'Javascript', 'file')`, the resulting file type is `"Javascript file"`.
* and the `'javascript'` darwin icon is used.
*
* If you call `darwinBundleDocumentType(..., 'bat', 'Windows command script')`, the file type is `"Windows command script"`,
* and the `'bat'` darwin icon is used.
*/
function darwinBundleDocumentType(extensions: string[], icon: string, nameOrSuffix?: string | DarwinDocumentSuffix, utis?: string[]): DarwinDocumentType {
// If given a suffix, generate a name from it. If not given anything, default to 'document'
if (isDocumentSuffix(nameOrSuffix) || !nameOrSuffix) {
nameOrSuffix = icon.charAt(0).toUpperCase() + icon.slice(1) + ' ' + (nameOrSuffix ?? 'document');
}
return {
name: nameOrSuffix,
role: 'Editor',
ostypes: ['TEXT', 'utxt', 'TUTX', '****'],
extensions,
iconFile: 'resources/darwin/' + icon.toLowerCase() + '.icns',
utis
};
}
/**
* Generate several `DarwinDocumentType`s with unique names and a shared icon.
* @param types A map of file type names to their associated file extensions.
* @param icon A darwin icon resource to use. For example, `'HTML'` would refer to `resources/darwin/html.icns`
*
* Examples:
* ```
* darwinBundleDocumentTypes({ 'C header file': 'h', 'C source code': 'c' },'c')
* darwinBundleDocumentTypes({ 'React source code': ['jsx', 'tsx'] }, 'react')
* ```
*/
function darwinBundleDocumentTypes(types: { [name: string]: string | string[] }, icon: string): DarwinDocumentType[] {
return Object.keys(types).map((name: string): DarwinDocumentType => {
const extensions = types[name];
return {
name,
role: 'Editor',
ostypes: ['TEXT', 'utxt', 'TUTX', '****'],
extensions: Array.isArray(extensions) ? extensions : [extensions],
iconFile: 'resources/darwin/' + icon + '.icns'
};
});
}
const { electronVersion, msBuildId } = util.getElectronVersion();
export const config = {
version: electronVersion,
tag: product.electronRepository ? `v${electronVersion}-${msBuildId}` : undefined,
productAppName: product.nameLong,
companyName: 'Microsoft Corporation',
copyright: 'Copyright (C) 2024 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools',
darwinHelpBookFolder: 'VS Code HelpBook',
darwinHelpBookName: 'VS Code HelpBook',
darwinBundleDocumentTypes: [
...darwinBundleDocumentTypes({ 'C header file': 'h', 'C source code': 'c' }, 'c'),
...darwinBundleDocumentTypes({ 'Git configuration file': ['gitattributes', 'gitconfig', 'gitignore'] }, 'config'),
...darwinBundleDocumentTypes({ 'HTML template document': ['asp', 'aspx', 'cshtml', 'jshtm', 'jsp', 'phtml', 'shtml'] }, 'html'),
darwinBundleDocumentType(['bat', 'cmd'], 'bat', 'Windows command script'),
darwinBundleDocumentType(['bowerrc'], 'Bower'),
darwinBundleDocumentType(['config', 'editorconfig', 'ini', 'cfg'], 'config', 'Configuration file'),
darwinBundleDocumentType(['hh', 'hpp', 'hxx', 'h++'], 'cpp', 'C++ header file'),
darwinBundleDocumentType(['cc', 'cpp', 'cxx', 'c++'], 'cpp', 'C++ source code'),
darwinBundleDocumentType(['m'], 'default', 'Objective-C source code'),
darwinBundleDocumentType(['mm'], 'cpp', 'Objective-C++ source code'),
darwinBundleDocumentType(['cs', 'csx'], 'csharp', 'C# source code'),
darwinBundleDocumentType(['css'], 'css', 'CSS'),
darwinBundleDocumentType(['go'], 'go', 'Go source code'),
darwinBundleDocumentType(['htm', 'html', 'xhtml'], 'HTML'),
darwinBundleDocumentType(['jade'], 'Jade'),
darwinBundleDocumentType(['jav', 'java'], 'Java'),
darwinBundleDocumentType(['js', 'jscsrc', 'jshintrc', 'mjs', 'cjs'], 'Javascript', 'file'),
darwinBundleDocumentType(['json'], 'JSON'),
darwinBundleDocumentType(['less'], 'Less'),
darwinBundleDocumentType(['markdown', 'md', 'mdoc', 'mdown', 'mdtext', 'mdtxt', 'mdwn', 'mkd', 'mkdn'], 'Markdown'),
darwinBundleDocumentType(['php'], 'PHP', 'source code'),
darwinBundleDocumentType(['ps1', 'psd1', 'psm1'], 'Powershell', 'script'),
darwinBundleDocumentType(['py', 'pyi'], 'Python', 'script'),
darwinBundleDocumentType(['gemspec', 'rb', 'erb'], 'Ruby', 'source code'),
darwinBundleDocumentType(['scss', 'sass'], 'SASS', 'file'),
darwinBundleDocumentType(['sql'], 'SQL', 'script'),
darwinBundleDocumentType(['ts'], 'TypeScript', 'file'),
darwinBundleDocumentType(['tsx', 'jsx'], 'React', 'source code'),
darwinBundleDocumentType(['vue'], 'Vue', 'source code'),
darwinBundleDocumentType(['ascx', 'csproj', 'dtd', 'plist', 'wxi', 'wxl', 'wxs', 'xml', 'xaml'], 'XML'),
darwinBundleDocumentType(['eyaml', 'eyml', 'yaml', 'yml'], 'YAML'),
darwinBundleDocumentType([
'bash', 'bash_login', 'bash_logout', 'bash_profile', 'bashrc',
'profile', 'rhistory', 'rprofile', 'sh', 'zlogin', 'zlogout',
'zprofile', 'zsh', 'zshenv', 'zshrc'
], 'Shell', 'script'),
// Default icon with specified names
...darwinBundleDocumentTypes({
'Clojure source code': ['clj', 'cljs', 'cljx', 'clojure'],
'VS Code workspace file': 'code-workspace',
'CoffeeScript source code': 'coffee',
'Comma Separated Values': 'csv',
'CMake script': 'cmake',
'Dart script': 'dart',
'Diff file': 'diff',
'Dockerfile': 'dockerfile',
'Gradle file': 'gradle',
'Groovy script': 'groovy',
'Makefile': ['makefile', 'mk'],
'Lua script': 'lua',
'Pug document': 'pug',
'Jupyter': 'ipynb',
'Lockfile': 'lock',
'Log file': 'log',
'Plain Text File': 'txt',
'Xcode project file': 'xcodeproj',
'Xcode workspace file': 'xcworkspace',
'Visual Basic script': 'vb',
'R source code': 'r',
'Rust source code': 'rs',
'Restructured Text document': 'rst',
'LaTeX document': ['tex', 'cls'],
'F# source code': 'fs',
'F# signature file': 'fsi',
'F# script': ['fsx', 'fsscript'],
'SVG document': ['svg'],
'TOML document': 'toml',
'Swift source code': 'swift',
}, 'default'),
// Default icon with default name
darwinBundleDocumentType([
'containerfile', 'ctp', 'dot', 'edn', 'handlebars', 'hbs', 'ml', 'mli',
'pl', 'pl6', 'pm', 'pm6', 'pod', 'pp', 'properties', 'psgi', 'rt', 't'
], 'default', product.nameLong + ' document'),
// Folder support ()
darwinBundleDocumentType([], 'default', 'Folder', ['public.folder'])
],
darwinBundleURLTypes: [{
role: 'Viewer',
name: product.nameLong,
urlSchemes: [product.urlProtocol]
}],
darwinForceDarkModeSupport: true,
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : undefined,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['GITHUB_TOKEN'],
repo: product.electronRepository || undefined,
validateChecksum: true,
checksumFile: path.join(root, 'build', 'checksums', 'electron.txt'),
};
function getElectron(arch: string): () => NodeJS.ReadWriteStream {
return () => {
const electron = require('@vscode/gulp-electron');
const json = require('gulp-json-editor') as typeof import('gulp-json-editor');
const electronOpts = {
...config,
platform: process.platform,
arch: arch === 'armhf' ? 'arm' : arch,
ffmpegChromium: false,
keepDefaultApp: true
};
return vfs.src('package.json')
.pipe(json({ name: product.nameShort }))
.pipe(electron(electronOpts))
.pipe(filter(['**', '!**/app/package.json']))
.pipe(vfs.dest('.build/electron'));
};
}
async function main(arch: string = process.arch): Promise {
const version = electronVersion;
const electronPath = path.join(root, '.build', 'electron');
const versionFile = path.join(electronPath, 'version');
const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`;
if (!isUpToDate) {
await util.rimraf(electronPath)();
await util.streamToPromise(getElectron(arch)());
}
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}
================================================
FILE: build/lib/extensions.js
================================================
"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 });
exports.fromMarketplace = fromMarketplace;
exports.fromVsix = fromVsix;
exports.fromGithub = fromGithub;
exports.packageNonNativeLocalExtensionsStream = packageNonNativeLocalExtensionsStream;
exports.packageNativeLocalExtensionsStream = packageNativeLocalExtensionsStream;
exports.packageAllLocalExtensionsStream = packageAllLocalExtensionsStream;
exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream;
exports.scanBuiltinExtensions = scanBuiltinExtensions;
exports.translatePackageJSON = translatePackageJSON;
exports.webpackExtensions = webpackExtensions;
exports.buildExtensionMedia = buildExtensionMedia;
const event_stream_1 = __importDefault(require("event-stream"));
const fs_1 = __importDefault(require("fs"));
const child_process_1 = __importDefault(require("child_process"));
const glob_1 = __importDefault(require("glob"));
const gulp_1 = __importDefault(require("gulp"));
const path_1 = __importDefault(require("path"));
const crypto_1 = __importDefault(require("crypto"));
const vinyl_1 = __importDefault(require("vinyl"));
const stats_1 = require("./stats");
const util2 = __importStar(require("./util"));
const vzip = require('gulp-vinyl-zip');
const gulp_filter_1 = __importDefault(require("gulp-filter"));
const gulp_rename_1 = __importDefault(require("gulp-rename"));
const fancy_log_1 = __importDefault(require("fancy-log"));
const ansi_colors_1 = __importDefault(require("ansi-colors"));
const gulp_buffer_1 = __importDefault(require("gulp-buffer"));
const jsoncParser = __importStar(require("jsonc-parser"));
const dependencies_1 = require("./dependencies");
const builtInExtensions_1 = require("./builtInExtensions");
const getVersion_1 = require("./getVersion");
const fetch_1 = require("./fetch");
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
const commit = (0, getVersion_1.getVersion)(root);
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
function minifyExtensionResources(input) {
const jsonFilter = (0, gulp_filter_1.default)(['**/*.json', '**/*.code-snippets'], { restore: true });
return input
.pipe(jsonFilter)
.pipe((0, gulp_buffer_1.default)())
.pipe(event_stream_1.default.mapSync((f) => {
const errors = [];
const value = jsoncParser.parse(f.contents.toString('utf8'), errors, { allowTrailingComma: true });
if (errors.length === 0) {
// file parsed OK => just stringify to drop whitespace and comments
f.contents = Buffer.from(JSON.stringify(value));
}
return f;
}))
.pipe(jsonFilter.restore);
}
function updateExtensionPackageJSON(input, update) {
const packageJsonFilter = (0, gulp_filter_1.default)('extensions/*/package.json', { restore: true });
return input
.pipe(packageJsonFilter)
.pipe((0, gulp_buffer_1.default)())
.pipe(event_stream_1.default.mapSync((f) => {
const data = JSON.parse(f.contents.toString('utf8'));
f.contents = Buffer.from(JSON.stringify(update(data)));
return f;
}))
.pipe(packageJsonFilter.restore);
}
function fromLocal(extensionPath, forWeb, disableMangle) {
const webpackConfigFileName = forWeb ? 'extension-browser.webpack.config.js' : 'extension.webpack.config.js';
const isWebPacked = fs_1.default.existsSync(path_1.default.join(extensionPath, webpackConfigFileName));
let input = isWebPacked
? fromLocalWebpack(extensionPath, webpackConfigFileName, disableMangle)
: fromLocalNormal(extensionPath);
if (isWebPacked) {
input = updateExtensionPackageJSON(input, (data) => {
delete data.scripts;
delete data.dependencies;
delete data.devDependencies;
if (data.main) {
data.main = data.main.replace('/out/', '/dist/');
}
return data;
});
}
return input;
}
function fromLocalWebpack(extensionPath, webpackConfigFileName, disableMangle) {
const vsce = require('@vscode/vsce');
const webpack = require('webpack');
const webpackGulp = require('webpack-stream');
const result = event_stream_1.default.through();
const packagedDependencies = [];
const packageJsonConfig = require(path_1.default.join(extensionPath, 'package.json'));
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path_1.default.join(extensionPath, webpackConfigFileName));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
packagedDependencies.push(key);
}
}
}
// TODO: add prune support based on packagedDependencies to vsce.PackageManager.Npm similar
// to vsce.PackageManager.Yarn.
// A static analysis showed there are no webpack externals that are dependencies of the current
// local extensions so we can use the vsce.PackageManager.None config to ignore dependencies list
// as a temporary workaround.
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.None, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path_1.default.join(extensionPath, fileName))
.map(filePath => new vinyl_1.default({
path: filePath,
stat: fs_1.default.statSync(filePath),
base: extensionPath,
contents: fs_1.default.createReadStream(filePath)
}));
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream.
const webpackConfigLocations = glob_1.default.sync(path_1.default.join(extensionPath, '**', webpackConfigFileName), { ignore: ['**/node_modules'] });
const webpackStreams = webpackConfigLocations.flatMap(webpackConfigPath => {
const webpackDone = (err, stats) => {
(0, fancy_log_1.default)(`Bundled extension: ${ansi_colors_1.default.yellow(path_1.default.join(path_1.default.basename(extensionPath), path_1.default.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
result.emit('error', err);
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('error', compilation.warnings.join('\n'));
}
};
const exportedConfig = require(webpackConfigPath);
return (Array.isArray(exportedConfig) ? exportedConfig : [exportedConfig]).map(config => {
const webpackConfig = {
...config,
...{ mode: 'production' }
};
if (disableMangle) {
if (Array.isArray(config.module.rules)) {
for (const rule of config.module.rules) {
if (Array.isArray(rule.use)) {
for (const use of rule.use) {
if (String(use.loader).endsWith('mangle-loader.js')) {
use.options.disabled = true;
}
}
}
}
}
}
const relativeOutputPath = path_1.default.relative(extensionPath, webpackConfig.output.path);
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(event_stream_1.default.through(function (data) {
data.stat = data.stat || {};
data.base = extensionPath;
this.emit('data', data);
}))
.pipe(event_stream_1.default.through(function (data) {
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
if (path_1.default.extname(data.basename) === '.js') {
const contents = data.contents.toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path_1.default.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
}), 'utf8');
}
this.emit('data', data);
}));
});
});
event_stream_1.default.merge(...webpackStreams, event_stream_1.default.readArray(files))
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
.pipe(result);
}).catch(err => {
console.error(extensionPath);
console.error(packagedDependencies);
result.emit('error', err);
});
return result.pipe((0, stats_1.createStatsStream)(path_1.default.basename(extensionPath)));
}
function fromLocalNormal(extensionPath) {
const vsce = require('@vscode/vsce');
const result = event_stream_1.default.through();
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Npm })
.then(fileNames => {
const files = fileNames
.map(fileName => path_1.default.join(extensionPath, fileName))
.map(filePath => new vinyl_1.default({
path: filePath,
stat: fs_1.default.statSync(filePath),
base: extensionPath,
contents: fs_1.default.createReadStream(filePath)
}));
event_stream_1.default.readArray(files).pipe(result);
})
.catch(err => result.emit('error', err));
return result.pipe((0, stats_1.createStatsStream)(path_1.default.basename(extensionPath)));
}
const userAgent = 'VSCode Build';
const baseHeaders = {
'X-Market-Client-Id': 'VSCode Build',
'User-Agent': userAgent,
'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2',
};
function fromMarketplace(serviceUrl, { name: extensionName, version, sha256, metadata }) {
const json = require('gulp-json-editor');
const [publisher, name] = extensionName.split('.');
const url = `${serviceUrl}/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`;
(0, fancy_log_1.default)('Downloading extension:', ansi_colors_1.default.yellow(`${extensionName}@${version}`), '...');
const packageJsonFilter = (0, gulp_filter_1.default)('package.json', { restore: true });
return (0, fetch_1.fetchUrls)('', {
base: url,
nodeFetchOptions: {
headers: baseHeaders
},
checksumSha256: sha256
})
.pipe(vzip.src())
.pipe((0, gulp_filter_1.default)('extension/**'))
.pipe((0, gulp_rename_1.default)(p => p.dirname = p.dirname.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe((0, gulp_buffer_1.default)())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
function fromVsix(vsixPath, { name: extensionName, version, sha256, metadata }) {
const json = require('gulp-json-editor');
(0, fancy_log_1.default)('Using local VSIX for extension:', ansi_colors_1.default.yellow(`${extensionName}@${version}`), '...');
const packageJsonFilter = (0, gulp_filter_1.default)('package.json', { restore: true });
return gulp_1.default.src(vsixPath)
.pipe((0, gulp_buffer_1.default)())
.pipe(event_stream_1.default.mapSync((f) => {
const hash = crypto_1.default.createHash('sha256');
hash.update(f.contents);
const checksum = hash.digest('hex');
if (checksum !== sha256) {
throw new Error(`Checksum mismatch for ${vsixPath} (expected ${sha256}, actual ${checksum}))`);
}
return f;
}))
.pipe(vzip.src())
.pipe((0, gulp_filter_1.default)('extension/**'))
.pipe((0, gulp_rename_1.default)(p => p.dirname = p.dirname.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe((0, gulp_buffer_1.default)())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
function fromGithub({ name, version, repo, sha256, metadata }) {
const json = require('gulp-json-editor');
(0, fancy_log_1.default)('Downloading extension from GH:', ansi_colors_1.default.yellow(`${name}@${version}`), '...');
const packageJsonFilter = (0, gulp_filter_1.default)('package.json', { restore: true });
return (0, fetch_1.fetchGithub)(new URL(repo).pathname, {
version,
name: name => name.endsWith('.vsix'),
checksumSha256: sha256
})
.pipe((0, gulp_buffer_1.default)())
.pipe(vzip.src())
.pipe((0, gulp_filter_1.default)('extension/**'))
.pipe((0, gulp_rename_1.default)(p => p.dirname = p.dirname.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe((0, gulp_buffer_1.default)())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
/**
* All extensions that are known to have some native component and thus must be built on the
* platform that is being built.
*/
const nativeExtensions = [
'microsoft-authentication',
];
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'vscode-colorize-perf-tests',
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
];
const marketplaceWebExtensionsExclude = new Set([
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
'ms-vscode.js-debug-companion',
'ms-vscode.js-debug',
'ms-vscode.vscode-js-profile-table'
]);
const productJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = productJson.builtInExtensions || [];
const webBuiltInExtensions = productJson.webBuiltInExtensions || [];
/**
* Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionManifestPropertiesService.ts`
*/
function isWebExtension(manifest) {
if (Boolean(manifest.browser)) {
return true;
}
if (Boolean(manifest.main)) {
return false;
}
// neither browser nor main
if (typeof manifest.extensionKind !== 'undefined') {
const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind];
if (extensionKind.indexOf('web') >= 0) {
return true;
}
}
if (typeof manifest.contributes !== 'undefined') {
for (const id of ['debuggers', 'terminal', 'typescriptServerPlugins']) {
if (manifest.contributes.hasOwnProperty(id)) {
return false;
}
}
}
return true;
}
/**
* Package local extensions that are known to not have native dependencies. Mutually exclusive to {@link packageNativeLocalExtensionsStream}.
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @returns a stream
*/
function packageNonNativeLocalExtensionsStream(forWeb, disableMangle) {
return doPackageLocalExtensionsStream(forWeb, disableMangle, false);
}
/**
* Package local extensions that are known to have native dependencies. Mutually exclusive to {@link packageNonNativeLocalExtensionsStream}.
* @note it's possible that the extension does not have native dependencies for the current platform, especially if building for the web,
* but we simplify the logic here by having a flat list of extensions (See {@link nativeExtensions}) that are known to have native
* dependencies on some platform and thus should be packaged on the platform that they are building for.
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @returns a stream
*/
function packageNativeLocalExtensionsStream(forWeb, disableMangle) {
return doPackageLocalExtensionsStream(forWeb, disableMangle, true);
}
/**
* Package all the local extensions... both those that are known to have native dependencies and those that are not.
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @returns a stream
*/
function packageAllLocalExtensionsStream(forWeb, disableMangle) {
return event_stream_1.default.merge([
packageNonNativeLocalExtensionsStream(forWeb, disableMangle),
packageNativeLocalExtensionsStream(forWeb, disableMangle)
]);
}
/**
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @param native build the extensions that are marked as having native dependencies
*/
function doPackageLocalExtensionsStream(forWeb, disableMangle, native) {
const nativeExtensionsSet = new Set(nativeExtensions);
const localExtensionsDescriptions = (glob_1.default.sync('extensions/*/package.json')
.map(manifestPath => {
const absoluteManifestPath = path_1.default.join(root, manifestPath);
const extensionPath = path_1.default.dirname(path_1.default.join(root, manifestPath));
const extensionName = path_1.default.basename(extensionPath);
return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath };
})
.filter(({ name }) => native ? nativeExtensionsSet.has(name) : !nativeExtensionsSet.has(name))
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true)));
const localExtensionsStream = minifyExtensionResources(event_stream_1.default.merge(...localExtensionsDescriptions.map(extension => {
return fromLocal(extension.path, forWeb, disableMangle)
.pipe((0, gulp_rename_1.default)(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
})));
let result;
if (forWeb) {
result = localExtensionsStream;
}
else {
// also include shared production node modules
const productionDependencies = (0, dependencies_1.getProductionDependencies)('extensions/');
const dependenciesSrc = productionDependencies.map(d => path_1.default.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat();
result = event_stream_1.default.merge(localExtensionsStream, gulp_1.default.src(dependenciesSrc, { base: '.' })
.pipe(util2.cleanNodeModules(path_1.default.join(root, 'build', '.moduleignore')))
.pipe(util2.cleanNodeModules(path_1.default.join(root, 'build', `.moduleignore.${process.platform}`))));
}
return (result
.pipe(util2.setExecutableBit(['**/*.sh'])));
}
function packageMarketplaceExtensionsStream(forWeb) {
const marketplaceExtensionsDescriptions = [
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
...(forWeb ? webBuiltInExtensions : [])
];
const marketplaceExtensionsStream = minifyExtensionResources(event_stream_1.default.merge(...marketplaceExtensionsDescriptions
.map(extension => {
const src = (0, builtInExtensions_1.getExtensionStream)(extension).pipe((0, gulp_rename_1.default)(p => p.dirname = `extensions/${p.dirname}`));
return updateExtensionPackageJSON(src, (data) => {
delete data.scripts;
delete data.dependencies;
delete data.devDependencies;
return data;
});
})));
return (marketplaceExtensionsStream
.pipe(util2.setExecutableBit(['**/*.sh'])));
}
function scanBuiltinExtensions(extensionsRoot, exclude = []) {
const scannedExtensions = [];
try {
const extensionsFolders = fs_1.default.readdirSync(extensionsRoot);
for (const extensionFolder of extensionsFolders) {
if (exclude.indexOf(extensionFolder) >= 0) {
continue;
}
const packageJSONPath = path_1.default.join(extensionsRoot, extensionFolder, 'package.json');
if (!fs_1.default.existsSync(packageJSONPath)) {
continue;
}
const packageJSON = JSON.parse(fs_1.default.readFileSync(packageJSONPath).toString('utf8'));
if (!isWebExtension(packageJSON)) {
continue;
}
const children = fs_1.default.readdirSync(path_1.default.join(extensionsRoot, extensionFolder));
const packageNLSPath = children.filter(child => child === 'package.nls.json')[0];
const packageNLS = packageNLSPath ? JSON.parse(fs_1.default.readFileSync(path_1.default.join(extensionsRoot, extensionFolder, packageNLSPath)).toString()) : undefined;
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
scannedExtensions.push({
extensionPath: extensionFolder,
packageJSON,
packageNLS,
readmePath: readme ? path_1.default.join(extensionFolder, readme) : undefined,
changelogPath: changelog ? path_1.default.join(extensionFolder, changelog) : undefined,
});
}
return scannedExtensions;
}
catch (ex) {
return scannedExtensions;
}
}
function translatePackageJSON(packageJSON, packageNLSPath) {
const CharCode_PC = '%'.charCodeAt(0);
const packageNls = JSON.parse(fs_1.default.readFileSync(packageNLSPath).toString());
const translate = (obj) => {
for (const key in obj) {
const val = obj[key];
if (Array.isArray(val)) {
val.forEach(translate);
}
else if (val && typeof val === 'object') {
translate(val);
}
else if (typeof val === 'string' && val.charCodeAt(0) === CharCode_PC && val.charCodeAt(val.length - 1) === CharCode_PC) {
const translated = packageNls[val.substr(1, val.length - 2)];
if (translated) {
obj[key] = typeof translated === 'string' ? translated : (typeof translated.message === 'string' ? translated.message : val);
}
}
}
};
translate(packageJSON);
return packageJSON;
}
const extensionsPath = path_1.default.join(root, 'extensions');
// Additional projects to run esbuild on. These typically build code for webviews
const esbuildMediaScripts = [
'markdown-language-features/esbuild-notebook.js',
'markdown-language-features/esbuild-preview.js',
'markdown-math/esbuild.js',
'notebook-renderers/esbuild.js',
'ipynb/esbuild.js',
'simple-browser/esbuild-preview.js',
];
async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
const webpack = require('webpack');
const webpackConfigs = [];
for (const { configPath, outputRoot } of webpackConfigLocations) {
const configOrFnOrArray = require(configPath);
function addConfig(configOrFnOrArray) {
for (const configOrFn of Array.isArray(configOrFnOrArray) ? configOrFnOrArray : [configOrFnOrArray]) {
const config = typeof configOrFn === 'function' ? configOrFn({}, {}) : configOrFn;
if (outputRoot) {
config.output.path = path_1.default.join(outputRoot, path_1.default.relative(path_1.default.dirname(configPath), config.output.path));
}
webpackConfigs.push(config);
}
}
addConfig(configOrFnOrArray);
}
function reporter(fullStats) {
if (Array.isArray(fullStats.children)) {
for (const stats of fullStats.children) {
const outputPath = stats.outputPath;
if (outputPath) {
const relativePath = path_1.default.relative(extensionsPath, outputPath).replace(/\\/g, '/');
const match = relativePath.match(/[^\/]+(\/server|\/client)?/);
(0, fancy_log_1.default)(`Finished ${ansi_colors_1.default.green(taskName)} ${ansi_colors_1.default.cyan(match[0])} with ${stats.errors.length} errors.`);
}
if (Array.isArray(stats.errors)) {
stats.errors.forEach((error) => {
fancy_log_1.default.error(error);
});
}
if (Array.isArray(stats.warnings)) {
stats.warnings.forEach((warning) => {
fancy_log_1.default.warn(warning);
});
}
}
}
}
return new Promise((resolve, reject) => {
if (isWatch) {
webpack(webpackConfigs).watch({}, (err, stats) => {
if (err) {
reject();
}
else {
reporter(stats?.toJson());
}
});
}
else {
webpack(webpackConfigs).run((err, stats) => {
if (err) {
fancy_log_1.default.error(err);
reject();
}
else {
reporter(stats?.toJson());
resolve();
}
});
}
});
}
async function esbuildExtensions(taskName, isWatch, scripts) {
function reporter(stdError, script) {
const matches = (stdError || '').match(/\> (.+): error: (.+)?/g);
(0, fancy_log_1.default)(`Finished ${ansi_colors_1.default.green(taskName)} ${script} with ${matches ? matches.length : 0} errors.`);
for (const match of matches || []) {
fancy_log_1.default.error(match);
}
}
const tasks = scripts.map(({ script, outputRoot }) => {
return new Promise((resolve, reject) => {
const args = [script];
if (isWatch) {
args.push('--watch');
}
if (outputRoot) {
args.push('--outputRoot', outputRoot);
}
const proc = child_process_1.default.execFile(process.argv[0], args, {}, (error, _stdout, stderr) => {
if (error) {
return reject(error);
}
reporter(stderr, script);
return resolve();
});
proc.stdout.on('data', (data) => {
(0, fancy_log_1.default)(`${ansi_colors_1.default.green(taskName)}: ${data.toString('utf8')}`);
});
});
});
return Promise.all(tasks);
}
async function buildExtensionMedia(isWatch, outputRoot) {
return esbuildExtensions('esbuilding extension media', isWatch, esbuildMediaScripts.map(p => ({
script: path_1.default.join(extensionsPath, p),
outputRoot: outputRoot ? path_1.default.join(root, outputRoot, path_1.default.dirname(p)) : undefined
})));
}
//# sourceMappingURL=extensions.js.map
================================================
FILE: build/lib/extensions.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import es from 'event-stream';
import fs from 'fs';
import cp from 'child_process';
import glob from 'glob';
import gulp from 'gulp';
import path from 'path';
import crypto from 'crypto';
import { Stream } from 'stream';
import File from 'vinyl';
import { createStatsStream } from './stats';
import * as util2 from './util';
const vzip = require('gulp-vinyl-zip');
import filter from 'gulp-filter';
import rename from 'gulp-rename';
import fancyLog from 'fancy-log';
import ansiColors from 'ansi-colors';
import buffer from 'gulp-buffer';
import * as jsoncParser from 'jsonc-parser';
import webpack from 'webpack';
import { getProductionDependencies } from './dependencies';
import { IExtensionDefinition, getExtensionStream } from './builtInExtensions';
import { getVersion } from './getVersion';
import { fetchUrls, fetchGithub } from './fetch';
const root = path.dirname(path.dirname(__dirname));
const commit = getVersion(root);
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
function minifyExtensionResources(input: Stream): Stream {
const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true });
return input
.pipe(jsonFilter)
.pipe(buffer())
.pipe(es.mapSync((f: File) => {
const errors: jsoncParser.ParseError[] = [];
const value = jsoncParser.parse(f.contents.toString('utf8'), errors, { allowTrailingComma: true });
if (errors.length === 0) {
// file parsed OK => just stringify to drop whitespace and comments
f.contents = Buffer.from(JSON.stringify(value));
}
return f;
}))
.pipe(jsonFilter.restore);
}
function updateExtensionPackageJSON(input: Stream, update: (data: any) => any): Stream {
const packageJsonFilter = filter('extensions/*/package.json', { restore: true });
return input
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(es.mapSync((f: File) => {
const data = JSON.parse(f.contents.toString('utf8'));
f.contents = Buffer.from(JSON.stringify(update(data)));
return f;
}))
.pipe(packageJsonFilter.restore);
}
function fromLocal(extensionPath: string, forWeb: boolean, disableMangle: boolean): Stream {
const webpackConfigFileName = forWeb ? 'extension-browser.webpack.config.js' : 'extension.webpack.config.js';
const isWebPacked = fs.existsSync(path.join(extensionPath, webpackConfigFileName));
let input = isWebPacked
? fromLocalWebpack(extensionPath, webpackConfigFileName, disableMangle)
: fromLocalNormal(extensionPath);
if (isWebPacked) {
input = updateExtensionPackageJSON(input, (data: any) => {
delete data.scripts;
delete data.dependencies;
delete data.devDependencies;
if (data.main) {
data.main = data.main.replace('/out/', '/dist/');
}
return data;
});
}
return input;
}
function fromLocalWebpack(extensionPath: string, webpackConfigFileName: string, disableMangle: boolean): Stream {
const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
const webpack = require('webpack');
const webpackGulp = require('webpack-stream');
const result = es.through();
const packagedDependencies: string[] = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path.join(extensionPath, webpackConfigFileName));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
packagedDependencies.push(key);
}
}
}
// TODO: add prune support based on packagedDependencies to vsce.PackageManager.Npm similar
// to vsce.PackageManager.Yarn.
// A static analysis showed there are no webpack externals that are dependencies of the current
// local extensions so we can use the vsce.PackageManager.None config to ignore dependencies list
// as a temporary workaround.
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.None, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath) as any
}));
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream.
const webpackConfigLocations = (glob.sync(
path.join(extensionPath, '**', webpackConfigFileName),
{ ignore: ['**/node_modules'] }
));
const webpackStreams = webpackConfigLocations.flatMap(webpackConfigPath => {
const webpackDone = (err: any, stats: any) => {
fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
result.emit('error', err);
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('error', compilation.warnings.join('\n'));
}
};
const exportedConfig = require(webpackConfigPath);
return (Array.isArray(exportedConfig) ? exportedConfig : [exportedConfig]).map(config => {
const webpackConfig = {
...config,
...{ mode: 'production' }
};
if (disableMangle) {
if (Array.isArray(config.module.rules)) {
for (const rule of config.module.rules) {
if (Array.isArray(rule.use)) {
for (const use of rule.use) {
if (String(use.loader).endsWith('mangle-loader.js')) {
use.options.disabled = true;
}
}
}
}
}
}
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(es.through(function (data) {
data.stat = data.stat || {};
data.base = extensionPath;
this.emit('data', data);
}))
.pipe(es.through(function (data: File) {
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
if (path.extname(data.basename) === '.js') {
const contents = (data.contents).toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
}), 'utf8');
}
this.emit('data', data);
}));
});
});
es.merge(...webpackStreams, es.readArray(files))
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
.pipe(result);
}).catch(err => {
console.error(extensionPath);
console.error(packagedDependencies);
result.emit('error', err);
});
return result.pipe(createStatsStream(path.basename(extensionPath)));
}
function fromLocalNormal(extensionPath: string): Stream {
const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
const result = es.through();
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Npm })
.then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath) as any
}));
es.readArray(files).pipe(result);
})
.catch(err => result.emit('error', err));
return result.pipe(createStatsStream(path.basename(extensionPath)));
}
const userAgent = 'VSCode Build';
const baseHeaders = {
'X-Market-Client-Id': 'VSCode Build',
'User-Agent': userAgent,
'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2',
};
export function fromMarketplace(serviceUrl: string, { name: extensionName, version, sha256, metadata }: IExtensionDefinition): Stream {
const json = require('gulp-json-editor') as typeof import('gulp-json-editor');
const [publisher, name] = extensionName.split('.');
const url = `${serviceUrl}/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`;
fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...');
const packageJsonFilter = filter('package.json', { restore: true });
return fetchUrls('', {
base: url,
nodeFetchOptions: {
headers: baseHeaders
},
checksumSha256: sha256
})
.pipe(vzip.src())
.pipe(filter('extension/**'))
.pipe(rename(p => p.dirname = p.dirname!.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
export function fromVsix(vsixPath: string, { name: extensionName, version, sha256, metadata }: IExtensionDefinition): Stream {
const json = require('gulp-json-editor') as typeof import('gulp-json-editor');
fancyLog('Using local VSIX for extension:', ansiColors.yellow(`${extensionName}@${version}`), '...');
const packageJsonFilter = filter('package.json', { restore: true });
return gulp.src(vsixPath)
.pipe(buffer())
.pipe(es.mapSync((f: File) => {
const hash = crypto.createHash('sha256');
hash.update(f.contents as Buffer);
const checksum = hash.digest('hex');
if (checksum !== sha256) {
throw new Error(`Checksum mismatch for ${vsixPath} (expected ${sha256}, actual ${checksum}))`);
}
return f;
}))
.pipe(vzip.src())
.pipe(filter('extension/**'))
.pipe(rename(p => p.dirname = p.dirname!.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
export function fromGithub({ name, version, repo, sha256, metadata }: IExtensionDefinition): Stream {
const json = require('gulp-json-editor') as typeof import('gulp-json-editor');
fancyLog('Downloading extension from GH:', ansiColors.yellow(`${name}@${version}`), '...');
const packageJsonFilter = filter('package.json', { restore: true });
return fetchGithub(new URL(repo).pathname, {
version,
name: name => name.endsWith('.vsix'),
checksumSha256: sha256
})
.pipe(buffer())
.pipe(vzip.src())
.pipe(filter('extension/**'))
.pipe(rename(p => p.dirname = p.dirname!.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
/**
* All extensions that are known to have some native component and thus must be built on the
* platform that is being built.
*/
const nativeExtensions = [
'microsoft-authentication',
];
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'vscode-colorize-perf-tests',
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
];
const marketplaceWebExtensionsExclude = new Set([
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
'ms-vscode.js-debug-companion',
'ms-vscode.js-debug',
'ms-vscode.vscode-js-profile-table'
]);
const productJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions: IExtensionDefinition[] = productJson.builtInExtensions || [];
const webBuiltInExtensions: IExtensionDefinition[] = productJson.webBuiltInExtensions || [];
type ExtensionKind = 'ui' | 'workspace' | 'web';
interface IExtensionManifest {
main?: string;
browser?: string;
extensionKind?: ExtensionKind | ExtensionKind[];
extensionPack?: string[];
extensionDependencies?: string[];
contributes?: { [id: string]: any };
}
/**
* Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionManifestPropertiesService.ts`
*/
function isWebExtension(manifest: IExtensionManifest): boolean {
if (Boolean(manifest.browser)) {
return true;
}
if (Boolean(manifest.main)) {
return false;
}
// neither browser nor main
if (typeof manifest.extensionKind !== 'undefined') {
const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind];
if (extensionKind.indexOf('web') >= 0) {
return true;
}
}
if (typeof manifest.contributes !== 'undefined') {
for (const id of ['debuggers', 'terminal', 'typescriptServerPlugins']) {
if (manifest.contributes.hasOwnProperty(id)) {
return false;
}
}
}
return true;
}
/**
* Package local extensions that are known to not have native dependencies. Mutually exclusive to {@link packageNativeLocalExtensionsStream}.
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @returns a stream
*/
export function packageNonNativeLocalExtensionsStream(forWeb: boolean, disableMangle: boolean): Stream {
return doPackageLocalExtensionsStream(forWeb, disableMangle, false);
}
/**
* Package local extensions that are known to have native dependencies. Mutually exclusive to {@link packageNonNativeLocalExtensionsStream}.
* @note it's possible that the extension does not have native dependencies for the current platform, especially if building for the web,
* but we simplify the logic here by having a flat list of extensions (See {@link nativeExtensions}) that are known to have native
* dependencies on some platform and thus should be packaged on the platform that they are building for.
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @returns a stream
*/
export function packageNativeLocalExtensionsStream(forWeb: boolean, disableMangle: boolean): Stream {
return doPackageLocalExtensionsStream(forWeb, disableMangle, true);
}
/**
* Package all the local extensions... both those that are known to have native dependencies and those that are not.
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @returns a stream
*/
export function packageAllLocalExtensionsStream(forWeb: boolean, disableMangle: boolean): Stream {
return es.merge([
packageNonNativeLocalExtensionsStream(forWeb, disableMangle),
packageNativeLocalExtensionsStream(forWeb, disableMangle)
]);
}
/**
* @param forWeb build the extensions that have web targets
* @param disableMangle disable the mangler
* @param native build the extensions that are marked as having native dependencies
*/
function doPackageLocalExtensionsStream(forWeb: boolean, disableMangle: boolean, native: boolean): Stream {
const nativeExtensionsSet = new Set(nativeExtensions);
const localExtensionsDescriptions = (
(glob.sync('extensions/*/package.json'))
.map(manifestPath => {
const absoluteManifestPath = path.join(root, manifestPath);
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath };
})
.filter(({ name }) => native ? nativeExtensionsSet.has(name) : !nativeExtensionsSet.has(name))
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true))
);
const localExtensionsStream = minifyExtensionResources(
es.merge(
...localExtensionsDescriptions.map(extension => {
return fromLocal(extension.path, forWeb, disableMangle)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
})
)
);
let result: Stream;
if (forWeb) {
result = localExtensionsStream;
} else {
// also include shared production node modules
const productionDependencies = getProductionDependencies('extensions/');
const dependenciesSrc = productionDependencies.map(d => path.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat();
result = es.merge(
localExtensionsStream,
gulp.src(dependenciesSrc, { base: '.' })
.pipe(util2.cleanNodeModules(path.join(root, 'build', '.moduleignore')))
.pipe(util2.cleanNodeModules(path.join(root, 'build', `.moduleignore.${process.platform}`))));
}
return (
result
.pipe(util2.setExecutableBit(['**/*.sh']))
);
}
export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream {
const marketplaceExtensionsDescriptions = [
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
...(forWeb ? webBuiltInExtensions : [])
];
const marketplaceExtensionsStream = minifyExtensionResources(
es.merge(
...marketplaceExtensionsDescriptions
.map(extension => {
const src = getExtensionStream(extension).pipe(rename(p => p.dirname = `extensions/${p.dirname}`));
return updateExtensionPackageJSON(src, (data: any) => {
delete data.scripts;
delete data.dependencies;
delete data.devDependencies;
return data;
});
})
)
);
return (
marketplaceExtensionsStream
.pipe(util2.setExecutableBit(['**/*.sh']))
);
}
export interface IScannedBuiltinExtension {
extensionPath: string;
packageJSON: any;
packageNLS?: any;
readmePath?: string;
changelogPath?: string;
}
export function scanBuiltinExtensions(extensionsRoot: string, exclude: string[] = []): IScannedBuiltinExtension[] {
const scannedExtensions: IScannedBuiltinExtension[] = [];
try {
const extensionsFolders = fs.readdirSync(extensionsRoot);
for (const extensionFolder of extensionsFolders) {
if (exclude.indexOf(extensionFolder) >= 0) {
continue;
}
const packageJSONPath = path.join(extensionsRoot, extensionFolder, 'package.json');
if (!fs.existsSync(packageJSONPath)) {
continue;
}
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8'));
if (!isWebExtension(packageJSON)) {
continue;
}
const children = fs.readdirSync(path.join(extensionsRoot, extensionFolder));
const packageNLSPath = children.filter(child => child === 'package.nls.json')[0];
const packageNLS = packageNLSPath ? JSON.parse(fs.readFileSync(path.join(extensionsRoot, extensionFolder, packageNLSPath)).toString()) : undefined;
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
scannedExtensions.push({
extensionPath: extensionFolder,
packageJSON,
packageNLS,
readmePath: readme ? path.join(extensionFolder, readme) : undefined,
changelogPath: changelog ? path.join(extensionFolder, changelog) : undefined,
});
}
return scannedExtensions;
} catch (ex) {
return scannedExtensions;
}
}
export function translatePackageJSON(packageJSON: string, packageNLSPath: string) {
interface NLSFormat {
[key: string]: string | { message: string; comment: string[] };
}
const CharCode_PC = '%'.charCodeAt(0);
const packageNls: NLSFormat = JSON.parse(fs.readFileSync(packageNLSPath).toString());
const translate = (obj: any) => {
for (const key in obj) {
const val = obj[key];
if (Array.isArray(val)) {
val.forEach(translate);
} else if (val && typeof val === 'object') {
translate(val);
} else if (typeof val === 'string' && val.charCodeAt(0) === CharCode_PC && val.charCodeAt(val.length - 1) === CharCode_PC) {
const translated = packageNls[val.substr(1, val.length - 2)];
if (translated) {
obj[key] = typeof translated === 'string' ? translated : (typeof translated.message === 'string' ? translated.message : val);
}
}
}
};
translate(packageJSON);
return packageJSON;
}
const extensionsPath = path.join(root, 'extensions');
// Additional projects to run esbuild on. These typically build code for webviews
const esbuildMediaScripts = [
'markdown-language-features/esbuild-notebook.js',
'markdown-language-features/esbuild-preview.js',
'markdown-math/esbuild.js',
'notebook-renderers/esbuild.js',
'ipynb/esbuild.js',
'simple-browser/esbuild-preview.js',
];
export async function webpackExtensions(taskName: string, isWatch: boolean, webpackConfigLocations: { configPath: string; outputRoot?: string }[]) {
const webpack = require('webpack') as typeof import('webpack');
const webpackConfigs: webpack.Configuration[] = [];
for (const { configPath, outputRoot } of webpackConfigLocations) {
const configOrFnOrArray = require(configPath);
function addConfig(configOrFnOrArray: webpack.Configuration | ((env: unknown, args: unknown) => webpack.Configuration) | webpack.Configuration[]) {
for (const configOrFn of Array.isArray(configOrFnOrArray) ? configOrFnOrArray : [configOrFnOrArray]) {
const config = typeof configOrFn === 'function' ? configOrFn({}, {}) : configOrFn;
if (outputRoot) {
config.output!.path = path.join(outputRoot, path.relative(path.dirname(configPath), config.output!.path!));
}
webpackConfigs.push(config);
}
}
addConfig(configOrFnOrArray);
}
function reporter(fullStats: any) {
if (Array.isArray(fullStats.children)) {
for (const stats of fullStats.children) {
const outputPath = stats.outputPath;
if (outputPath) {
const relativePath = path.relative(extensionsPath, outputPath).replace(/\\/g, '/');
const match = relativePath.match(/[^\/]+(\/server|\/client)?/);
fancyLog(`Finished ${ansiColors.green(taskName)} ${ansiColors.cyan(match![0])} with ${stats.errors.length} errors.`);
}
if (Array.isArray(stats.errors)) {
stats.errors.forEach((error: any) => {
fancyLog.error(error);
});
}
if (Array.isArray(stats.warnings)) {
stats.warnings.forEach((warning: any) => {
fancyLog.warn(warning);
});
}
}
}
}
return new Promise((resolve, reject) => {
if (isWatch) {
webpack(webpackConfigs).watch({}, (err, stats) => {
if (err) {
reject();
} else {
reporter(stats?.toJson());
}
});
} else {
webpack(webpackConfigs).run((err, stats) => {
if (err) {
fancyLog.error(err);
reject();
} else {
reporter(stats?.toJson());
resolve();
}
});
}
});
}
async function esbuildExtensions(taskName: string, isWatch: boolean, scripts: { script: string; outputRoot?: string }[]) {
function reporter(stdError: string, script: string) {
const matches = (stdError || '').match(/\> (.+): error: (.+)?/g);
fancyLog(`Finished ${ansiColors.green(taskName)} ${script} with ${matches ? matches.length : 0} errors.`);
for (const match of matches || []) {
fancyLog.error(match);
}
}
const tasks = scripts.map(({ script, outputRoot }) => {
return new Promise((resolve, reject) => {
const args = [script];
if (isWatch) {
args.push('--watch');
}
if (outputRoot) {
args.push('--outputRoot', outputRoot);
}
const proc = cp.execFile(process.argv[0], args, {}, (error, _stdout, stderr) => {
if (error) {
return reject(error);
}
reporter(stderr, script);
return resolve();
});
proc.stdout!.on('data', (data) => {
fancyLog(`${ansiColors.green(taskName)}: ${data.toString('utf8')}`);
});
});
});
return Promise.all(tasks);
}
export async function buildExtensionMedia(isWatch: boolean, outputRoot?: string) {
return esbuildExtensions('esbuilding extension media', isWatch, esbuildMediaScripts.map(p => ({
script: path.join(extensionsPath, p),
outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined
})));
}
================================================
FILE: build/lib/fetch.js
================================================
"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.fetchUrls = fetchUrls;
exports.fetchUrl = fetchUrl;
exports.fetchGithub = fetchGithub;
const event_stream_1 = __importDefault(require("event-stream"));
const vinyl_1 = __importDefault(require("vinyl"));
const fancy_log_1 = __importDefault(require("fancy-log"));
const ansi_colors_1 = __importDefault(require("ansi-colors"));
const crypto_1 = __importDefault(require("crypto"));
const through2_1 = __importDefault(require("through2"));
function fetchUrls(urls, options) {
if (options === undefined) {
options = {};
}
if (typeof options.base !== 'string' && options.base !== null) {
options.base = '/';
}
if (!Array.isArray(urls)) {
urls = [urls];
}
return event_stream_1.default.readArray(urls).pipe(event_stream_1.default.map((data, cb) => {
const url = [options.base, data].join('');
fetchUrl(url, options).then(file => {
cb(undefined, file);
}, error => {
cb(error);
});
}));
}
async function fetchUrl(url, options, retries = 10, retryDelay = 1000) {
const verbose = !!options.verbose || !!process.env['CI'] || !!process.env['BUILD_ARTIFACTSTAGINGDIRECTORY'];
try {
let startTime = 0;
if (verbose) {
(0, fancy_log_1.default)(`Start fetching ${ansi_colors_1.default.magenta(url)}${retries !== 10 ? ` (${10 - retries} retry)` : ''}`);
startTime = new Date().getTime();
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30 * 1000);
try {
const response = await fetch(url, {
...options.nodeFetchOptions,
signal: controller.signal /* Typings issue with lib.dom.d.ts */
});
if (verbose) {
(0, fancy_log_1.default)(`Fetch completed: Status ${response.status}. Took ${ansi_colors_1.default.magenta(`${new Date().getTime() - startTime} ms`)}`);
}
if (response.ok && (response.status >= 200 && response.status < 300)) {
const contents = Buffer.from(await response.arrayBuffer());
if (options.checksumSha256) {
const actualSHA256Checksum = crypto_1.default.createHash('sha256').update(contents).digest('hex');
if (actualSHA256Checksum !== options.checksumSha256) {
throw new Error(`Checksum mismatch for ${ansi_colors_1.default.cyan(url)} (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`);
}
else if (verbose) {
(0, fancy_log_1.default)(`Verified SHA256 checksums match for ${ansi_colors_1.default.cyan(url)}`);
}
}
else if (verbose) {
(0, fancy_log_1.default)(`Skipping checksum verification for ${ansi_colors_1.default.cyan(url)} because no expected checksum was provided`);
}
if (verbose) {
(0, fancy_log_1.default)(`Fetched response body buffer: ${ansi_colors_1.default.magenta(`${contents.byteLength} bytes`)}`);
}
return new vinyl_1.default({
cwd: '/',
base: options.base,
path: url,
contents
});
}
let err = `Request ${ansi_colors_1.default.magenta(url)} failed with status code: ${response.status}`;
if (response.status === 403) {
err += ' (you may be rate limited)';
}
throw new Error(err);
}
finally {
clearTimeout(timeout);
}
}
catch (e) {
if (verbose) {
(0, fancy_log_1.default)(`Fetching ${ansi_colors_1.default.cyan(url)} failed: ${e}`);
}
if (retries > 0) {
await new Promise(resolve => setTimeout(resolve, retryDelay));
return fetchUrl(url, options, retries - 1, retryDelay);
}
throw e;
}
}
const ghApiHeaders = {
Accept: 'application/vnd.github.v3+json',
'User-Agent': 'VSCode Build',
};
if (process.env.GITHUB_TOKEN) {
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
}
const ghDownloadHeaders = {
...ghApiHeaders,
Accept: 'application/octet-stream',
};
/**
* @param repo for example `Microsoft/vscode`
* @param version for example `16.17.1` - must be a valid releases tag
* @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists
* @returns a stream with the asset as file
*/
function fetchGithub(repo, options) {
return fetchUrls(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${options.version}`, {
base: 'https://api.github.com',
verbose: options.verbose,
nodeFetchOptions: { headers: ghApiHeaders }
}).pipe(through2_1.default.obj(async function (file, _enc, callback) {
const assetFilter = typeof options.name === 'string' ? (name) => name === options.name : options.name;
const asset = JSON.parse(file.contents.toString()).assets.find((a) => assetFilter(a.name));
if (!asset) {
return callback(new Error(`Could not find asset in release of ${repo} @ ${options.version}`));
}
try {
callback(null, await fetchUrl(asset.url, {
nodeFetchOptions: { headers: ghDownloadHeaders },
verbose: options.verbose,
checksumSha256: options.checksumSha256
}));
}
catch (error) {
callback(error);
}
}));
}
//# sourceMappingURL=fetch.js.map
================================================
FILE: build/lib/fetch.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import es from 'event-stream';
import VinylFile from 'vinyl';
import log from 'fancy-log';
import ansiColors from 'ansi-colors';
import crypto from 'crypto';
import through2 from 'through2';
import { Stream } from 'stream';
export interface IFetchOptions {
base?: string;
nodeFetchOptions?: RequestInit;
verbose?: boolean;
checksumSha256?: string;
}
export function fetchUrls(urls: string[] | string, options: IFetchOptions): es.ThroughStream {
if (options === undefined) {
options = {};
}
if (typeof options.base !== 'string' && options.base !== null) {
options.base = '/';
}
if (!Array.isArray(urls)) {
urls = [urls];
}
return es.readArray(urls).pipe(es.map((data: string, cb) => {
const url = [options.base, data].join('');
fetchUrl(url, options).then(file => {
cb(undefined, file);
}, error => {
cb(error);
});
}));
}
export async function fetchUrl(url: string, options: IFetchOptions, retries = 10, retryDelay = 1000): Promise {
const verbose = !!options.verbose || !!process.env['CI'] || !!process.env['BUILD_ARTIFACTSTAGINGDIRECTORY'];
try {
let startTime = 0;
if (verbose) {
log(`Start fetching ${ansiColors.magenta(url)}${retries !== 10 ? ` (${10 - retries} retry)` : ''}`);
startTime = new Date().getTime();
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30 * 1000);
try {
const response = await fetch(url, {
...options.nodeFetchOptions,
signal: controller.signal as any /* Typings issue with lib.dom.d.ts */
});
if (verbose) {
log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`);
}
if (response.ok && (response.status >= 200 && response.status < 300)) {
const contents = Buffer.from(await response.arrayBuffer());
if (options.checksumSha256) {
const actualSHA256Checksum = crypto.createHash('sha256').update(contents).digest('hex');
if (actualSHA256Checksum !== options.checksumSha256) {
throw new Error(`Checksum mismatch for ${ansiColors.cyan(url)} (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`);
} else if (verbose) {
log(`Verified SHA256 checksums match for ${ansiColors.cyan(url)}`);
}
} else if (verbose) {
log(`Skipping checksum verification for ${ansiColors.cyan(url)} because no expected checksum was provided`);
}
if (verbose) {
log(`Fetched response body buffer: ${ansiColors.magenta(`${(contents as Buffer).byteLength} bytes`)}`);
}
return new VinylFile({
cwd: '/',
base: options.base,
path: url,
contents
});
}
let err = `Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`;
if (response.status === 403) {
err += ' (you may be rate limited)';
}
throw new Error(err);
} finally {
clearTimeout(timeout);
}
} catch (e) {
if (verbose) {
log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`);
}
if (retries > 0) {
await new Promise(resolve => setTimeout(resolve, retryDelay));
return fetchUrl(url, options, retries - 1, retryDelay);
}
throw e;
}
}
const ghApiHeaders: Record = {
Accept: 'application/vnd.github.v3+json',
'User-Agent': 'VSCode Build',
};
if (process.env.GITHUB_TOKEN) {
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
}
const ghDownloadHeaders = {
...ghApiHeaders,
Accept: 'application/octet-stream',
};
export interface IGitHubAssetOptions {
version: string;
name: string | ((name: string) => boolean);
checksumSha256?: string;
verbose?: boolean;
}
/**
* @param repo for example `Microsoft/vscode`
* @param version for example `16.17.1` - must be a valid releases tag
* @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists
* @returns a stream with the asset as file
*/
export function fetchGithub(repo: string, options: IGitHubAssetOptions): Stream {
return fetchUrls(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${options.version}`, {
base: 'https://api.github.com',
verbose: options.verbose,
nodeFetchOptions: { headers: ghApiHeaders }
}).pipe(through2.obj(async function (file, _enc, callback) {
const assetFilter = typeof options.name === 'string' ? (name: string) => name === options.name : options.name;
const asset = JSON.parse(file.contents.toString()).assets.find((a: { name: string }) => assetFilter(a.name));
if (!asset) {
return callback(new Error(`Could not find asset in release of ${repo} @ ${options.version}`));
}
try {
callback(null, await fetchUrl(asset.url, {
nodeFetchOptions: { headers: ghDownloadHeaders },
verbose: options.verbose,
checksumSha256: options.checksumSha256
}));
} catch (error) {
callback(error);
}
}));
}
================================================
FILE: build/lib/formatter.js
================================================
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.format = format;
/*---------------------------------------------------------------------------------------------
* 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 typescript_1 = __importDefault(require("typescript"));
class LanguageServiceHost {
files = {};
addFile(fileName, text) {
this.files[fileName] = typescript_1.default.ScriptSnapshot.fromString(text);
}
fileExists(path) {
return !!this.files[path];
}
readFile(path) {
return this.files[path]?.getText(0, this.files[path].getLength());
}
// for ts.LanguageServiceHost
getCompilationSettings = () => typescript_1.default.getDefaultCompilerOptions();
getScriptFileNames = () => Object.keys(this.files);
getScriptVersion = (_fileName) => '0';
getScriptSnapshot = (fileName) => this.files[fileName];
getCurrentDirectory = () => process.cwd();
getDefaultLibFileName = (options) => typescript_1.default.getDefaultLibFilePath(options);
}
const defaults = {
baseIndentSize: 0,
indentSize: 4,
tabSize: 4,
indentStyle: typescript_1.default.IndentStyle.Smart,
newLineCharacter: '\r\n',
convertTabsToSpaces: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterConstructor: false,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceAfterTypeAssertion: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
insertSpaceBeforeTypeAnnotation: false,
};
const getOverrides = (() => {
let value;
return () => {
value ??= JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '..', '..', 'tsfmt.json'), 'utf8'));
return value;
};
})();
function format(fileName, text) {
const host = new LanguageServiceHost();
host.addFile(fileName, text);
const languageService = typescript_1.default.createLanguageService(host);
const edits = languageService.getFormattingEditsForDocument(fileName, { ...defaults, ...getOverrides() });
edits
.sort((a, b) => a.span.start - b.span.start)
.reverse()
.forEach(edit => {
const head = text.slice(0, edit.span.start);
const tail = text.slice(edit.span.start + edit.span.length);
text = `${head}${edit.newText}${tail}`;
});
return text;
}
//# sourceMappingURL=formatter.js.map
================================================
FILE: build/lib/formatter.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import fs from 'fs';
import path from 'path';
import ts from 'typescript';
class LanguageServiceHost implements ts.LanguageServiceHost {
files: ts.MapLike = {};
addFile(fileName: string, text: string) {
this.files[fileName] = ts.ScriptSnapshot.fromString(text);
}
fileExists(path: string): boolean {
return !!this.files[path];
}
readFile(path: string): string | undefined {
return this.files[path]?.getText(0, this.files[path]!.getLength());
}
// for ts.LanguageServiceHost
getCompilationSettings = () => ts.getDefaultCompilerOptions();
getScriptFileNames = () => Object.keys(this.files);
getScriptVersion = (_fileName: string) => '0';
getScriptSnapshot = (fileName: string) => this.files[fileName];
getCurrentDirectory = () => process.cwd();
getDefaultLibFileName = (options: ts.CompilerOptions) => ts.getDefaultLibFilePath(options);
}
const defaults: ts.FormatCodeSettings = {
baseIndentSize: 0,
indentSize: 4,
tabSize: 4,
indentStyle: ts.IndentStyle.Smart,
newLineCharacter: '\r\n',
convertTabsToSpaces: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterConstructor: false,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceAfterTypeAssertion: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
insertSpaceBeforeTypeAnnotation: false,
};
const getOverrides = (() => {
let value: ts.FormatCodeSettings | undefined;
return () => {
value ??= JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'tsfmt.json'), 'utf8'));
return value;
};
})();
export function format(fileName: string, text: string) {
const host = new LanguageServiceHost();
host.addFile(fileName, text);
const languageService = ts.createLanguageService(host);
const edits = languageService.getFormattingEditsForDocument(fileName, { ...defaults, ...getOverrides() });
edits
.sort((a, b) => a.span.start - b.span.start)
.reverse()
.forEach(edit => {
const head = text.slice(0, edit.span.start);
const tail = text.slice(edit.span.start + edit.span.length);
text = `${head}${edit.newText}${tail}`;
});
return text;
}
================================================
FILE: build/lib/getVersion.js
================================================
"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 });
exports.getVersion = getVersion;
const git = __importStar(require("./git"));
function getVersion(root) {
let version = process.env['BUILD_SOURCEVERSION'];
if (!version || !/^[0-9a-f]{40}$/i.test(version.trim())) {
version = git.getVersion(root);
}
return version;
}
//# sourceMappingURL=getVersion.js.map
================================================
FILE: build/lib/getVersion.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 git from './git';
export function getVersion(root: string): string | undefined {
let version = process.env['BUILD_SOURCEVERSION'];
if (!version || !/^[0-9a-f]{40}$/i.test(version.trim())) {
version = git.getVersion(root);
}
return version;
}
================================================
FILE: build/lib/git.js
================================================
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
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 path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
/**
* Returns the sha1 commit version of a repository or undefined in case of failure.
*/
function getVersion(repo) {
const git = path_1.default.join(repo, '.git');
const headPath = path_1.default.join(git, 'HEAD');
let head;
try {
head = fs_1.default.readFileSync(headPath, 'utf8').trim();
}
catch (e) {
return undefined;
}
if (/^[0-9a-f]{40}$/i.test(head)) {
return head;
}
const refMatch = /^ref: (.*)$/.exec(head);
if (!refMatch) {
return undefined;
}
const ref = refMatch[1];
const refPath = path_1.default.join(git, ref);
try {
return fs_1.default.readFileSync(refPath, 'utf8').trim();
}
catch (e) {
// noop
}
const packedRefsPath = path_1.default.join(git, 'packed-refs');
let refsRaw;
try {
refsRaw = fs_1.default.readFileSync(packedRefsPath, 'utf8').trim();
}
catch (e) {
return undefined;
}
const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
let refsMatch;
const refs = {};
while (refsMatch = refsRegex.exec(refsRaw)) {
refs[refsMatch[2]] = refsMatch[1];
}
return refs[ref];
}
//# sourceMappingURL=git.js.map
================================================
FILE: build/lib/git.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import path from 'path';
import fs from 'fs';
/**
* Returns the sha1 commit version of a repository or undefined in case of failure.
*/
export function getVersion(repo: string): string | undefined {
const git = path.join(repo, '.git');
const headPath = path.join(git, 'HEAD');
let head: string;
try {
head = fs.readFileSync(headPath, 'utf8').trim();
} catch (e) {
return undefined;
}
if (/^[0-9a-f]{40}$/i.test(head)) {
return head;
}
const refMatch = /^ref: (.*)$/.exec(head);
if (!refMatch) {
return undefined;
}
const ref = refMatch[1];
const refPath = path.join(git, ref);
try {
return fs.readFileSync(refPath, 'utf8').trim();
} catch (e) {
// noop
}
const packedRefsPath = path.join(git, 'packed-refs');
let refsRaw: string;
try {
refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim();
} catch (e) {
return undefined;
}
const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
let refsMatch: RegExpExecArray | null;
const refs: { [ref: string]: string } = {};
while (refsMatch = refsRegex.exec(refsRaw)) {
refs[refsMatch[2]] = refsMatch[1];
}
return refs[ref];
}
================================================
FILE: build/lib/i18n.js
================================================
"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.EXTERNAL_EXTENSIONS = exports.XLF = exports.Line = exports.extraLanguages = exports.defaultLanguages = void 0;
exports.processNlsFiles = processNlsFiles;
exports.getResource = getResource;
exports.createXlfFilesForCoreBundle = createXlfFilesForCoreBundle;
exports.createXlfFilesForExtensions = createXlfFilesForExtensions;
exports.createXlfFilesForIsl = createXlfFilesForIsl;
exports.prepareI18nPackFiles = prepareI18nPackFiles;
exports.prepareIslFiles = prepareIslFiles;
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const event_stream_1 = require("event-stream");
const gulp_merge_json_1 = __importDefault(require("gulp-merge-json"));
const vinyl_1 = __importDefault(require("vinyl"));
const xml2js_1 = __importDefault(require("xml2js"));
const gulp_1 = __importDefault(require("gulp"));
const fancy_log_1 = __importDefault(require("fancy-log"));
const ansi_colors_1 = __importDefault(require("ansi-colors"));
const iconv_lite_umd_1 = __importDefault(require("@vscode/iconv-lite-umd"));
const l10n_dev_1 = require("@vscode/l10n-dev");
const REPO_ROOT_PATH = path_1.default.join(__dirname, '../..');
function log(message, ...rest) {
(0, fancy_log_1.default)(ansi_colors_1.default.green('[i18n]'), message, ...rest);
}
exports.defaultLanguages = [
{ id: 'zh-tw', folderName: 'cht', translationId: 'zh-hant' },
{ id: 'zh-cn', folderName: 'chs', translationId: 'zh-hans' },
{ id: 'ja', folderName: 'jpn' },
{ id: 'ko', folderName: 'kor' },
{ id: 'de', folderName: 'deu' },
{ id: 'fr', folderName: 'fra' },
{ id: 'es', folderName: 'esn' },
{ id: 'ru', folderName: 'rus' },
{ id: 'it', folderName: 'ita' }
];
// languages requested by the community to non-stable builds
exports.extraLanguages = [
{ id: 'pt-br', folderName: 'ptb' },
{ id: 'hu', folderName: 'hun' },
{ id: 'tr', folderName: 'trk' }
];
var LocalizeInfo;
(function (LocalizeInfo) {
function is(value) {
const candidate = value;
return candidate && typeof candidate.key === 'string' && (candidate.comment === undefined || (Array.isArray(candidate.comment) && candidate.comment.every(element => typeof element === 'string')));
}
LocalizeInfo.is = is;
})(LocalizeInfo || (LocalizeInfo = {}));
var BundledFormat;
(function (BundledFormat) {
function is(value) {
if (value === undefined) {
return false;
}
const candidate = value;
const length = Object.keys(value).length;
return length === 3 && !!candidate.keys && !!candidate.messages && !!candidate.bundles;
}
BundledFormat.is = is;
})(BundledFormat || (BundledFormat = {}));
var NLSKeysFormat;
(function (NLSKeysFormat) {
function is(value) {
if (value === undefined) {
return false;
}
const candidate = value;
return Array.isArray(candidate) && Array.isArray(candidate[1]);
}
NLSKeysFormat.is = is;
})(NLSKeysFormat || (NLSKeysFormat = {}));
class Line {
buffer = [];
constructor(indent = 0) {
if (indent > 0) {
this.buffer.push(new Array(indent + 1).join(' '));
}
}
append(value) {
this.buffer.push(value);
return this;
}
toString() {
return this.buffer.join('');
}
}
exports.Line = Line;
class TextModel {
_lines;
constructor(contents) {
this._lines = contents.split(/\r\n|\r|\n/);
}
get lines() {
return this._lines;
}
}
class XLF {
project;
buffer;
files;
numberOfMessages;
constructor(project) {
this.project = project;
this.buffer = [];
this.files = Object.create(null);
this.numberOfMessages = 0;
}
toString() {
this.appendHeader();
const files = Object.keys(this.files).sort();
for (const file of files) {
this.appendNewLine(``, 2);
const items = this.files[file].sort((a, b) => {
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
for (const item of items) {
this.addStringItem(file, item);
}
this.appendNewLine('');
}
this.appendFooter();
return this.buffer.join('\r\n');
}
addFile(original, keys, messages) {
if (keys.length === 0) {
console.log('No keys in ' + original);
return;
}
if (keys.length !== messages.length) {
throw new Error(`Unmatching keys(${keys.length}) and messages(${messages.length}).`);
}
this.numberOfMessages += keys.length;
this.files[original] = [];
const existingKeys = new Set();
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
let realKey;
let comment;
if (typeof key === 'string') {
realKey = key;
comment = undefined;
}
else if (LocalizeInfo.is(key)) {
realKey = key.key;
if (key.comment && key.comment.length > 0) {
comment = key.comment.map(comment => encodeEntities(comment)).join('\r\n');
}
}
if (!realKey || existingKeys.has(realKey)) {
continue;
}
existingKeys.add(realKey);
const message = encodeEntities(messages[i]);
this.files[original].push({ id: realKey, message: message, comment: comment });
}
}
addStringItem(file, item) {
if (!item.id || item.message === undefined || item.message === null) {
throw new Error(`No item ID or value specified: ${JSON.stringify(item)}. File: ${file}`);
}
if (item.message.length === 0) {
log(`Item with id ${item.id} in file ${file} has an empty message.`);
}
this.appendNewLine(``, 4);
this.appendNewLine(`${item.message}`, 6);
if (item.comment) {
this.appendNewLine(`${item.comment}`, 6);
}
this.appendNewLine('', 4);
}
appendHeader() {
this.appendNewLine('', 0);
this.appendNewLine('', 0);
}
appendFooter() {
this.appendNewLine('', 0);
}
appendNewLine(content, indent) {
const line = new Line(indent);
line.append(content);
this.buffer.push(line.toString());
}
static parse = function (xlfString) {
return new Promise((resolve, reject) => {
const parser = new xml2js_1.default.Parser();
const files = [];
parser.parseString(xlfString, function (err, result) {
if (err) {
reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`));
}
const fileNodes = result['xliff']['file'];
if (!fileNodes) {
reject(new Error(`XLF parsing error: XLIFF file does not contain "xliff" or "file" node(s) required for parsing.`));
}
fileNodes.forEach((file) => {
const name = file.$.original;
if (!name) {
reject(new Error(`XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file.`));
}
const language = file.$['target-language'];
if (!language) {
reject(new Error(`XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.`));
}
const messages = {};
const transUnits = file.body[0]['trans-unit'];
if (transUnits) {
transUnits.forEach((unit) => {
const key = unit.$.id;
if (!unit.target) {
return; // No translation available
}
let val = unit.target[0];
if (typeof val !== 'string') {
// We allow empty source values so support them for translations as well.
val = val._ ? val._ : '';
}
if (!key) {
reject(new Error(`XLF parsing error: trans-unit ${JSON.stringify(unit, undefined, 0)} defined in file ${name} is missing the ID attribute.`));
return;
}
messages[key] = decodeEntities(val);
});
files.push({ messages, name, language: language.toLowerCase() });
}
});
resolve(files);
});
});
};
}
exports.XLF = XLF;
function sortLanguages(languages) {
return languages.sort((a, b) => {
return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
});
}
function stripComments(content) {
// Copied from stripComments.js
//
// First group matches a double quoted string
// Second group matches a single quoted string
// Third group matches a multi line comment
// Forth group matches a single line comment
// Fifth group matches a trailing comma
const regexp = /("[^"\\]*(?:\\.[^"\\]*)*")|('[^'\\]*(?:\\.[^'\\]*)*')|(\/\*[^\/\*]*(?:(?:\*|\/)[^\/\*]*)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))|(,\s*[}\]])/g;
const result = content.replace(regexp, (match, _m1, _m2, m3, m4, m5) => {
// Only one of m1, m2, m3, m4, m5 matches
if (m3) {
// A block comment. Replace with nothing
return '';
}
else if (m4) {
// Since m4 is a single line comment is is at least of length 2 (e.g. //)
// If it ends in \r?\n then keep it.
const length = m4.length;
if (m4[length - 1] === '\n') {
return m4[length - 2] === '\r' ? '\r\n' : '\n';
}
else {
return '';
}
}
else if (m5) {
// Remove the trailing comma
return match.substring(1);
}
else {
// We match a string
return match;
}
});
return result;
}
function processCoreBundleFormat(base, fileHeader, languages, json, emitter) {
const languageDirectory = path_1.default.join(REPO_ROOT_PATH, '..', 'vscode-loc', 'i18n');
if (!fs_1.default.existsSync(languageDirectory)) {
log(`No VS Code localization repository found. Looking at ${languageDirectory}`);
log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`);
}
const sortedLanguages = sortLanguages(languages);
sortedLanguages.forEach((language) => {
if (process.env['VSCODE_BUILD_VERBOSE']) {
log(`Generating nls bundles for: ${language.id}`);
}
const languageFolderName = language.translationId || language.id;
const i18nFile = path_1.default.join(languageDirectory, `vscode-language-pack-${languageFolderName}`, 'translations', 'main.i18n.json');
let allMessages;
if (fs_1.default.existsSync(i18nFile)) {
const content = stripComments(fs_1.default.readFileSync(i18nFile, 'utf8'));
allMessages = JSON.parse(content);
}
let nlsIndex = 0;
const nlsResult = [];
for (const [moduleId, nlsKeys] of json) {
const moduleTranslations = allMessages?.contents[moduleId];
for (const nlsKey of nlsKeys) {
nlsResult.push(moduleTranslations?.[nlsKey]); // pushing `undefined` is fine, as we keep english strings as fallback for monaco editor in the build
nlsIndex++;
}
}
emitter.queue(new vinyl_1.default({
contents: Buffer.from(`${fileHeader}
globalThis._VSCODE_NLS_MESSAGES=${JSON.stringify(nlsResult)};
globalThis._VSCODE_NLS_LANGUAGE=${JSON.stringify(language.id)};`),
base,
path: `${base}/nls.messages.${language.id}.js`
}));
});
}
function processNlsFiles(opts) {
return (0, event_stream_1.through)(function (file) {
const fileName = path_1.default.basename(file.path);
if (fileName === 'nls.keys.json') {
try {
const contents = file.contents.toString('utf8');
const json = JSON.parse(contents);
if (NLSKeysFormat.is(json)) {
processCoreBundleFormat(file.base, opts.fileHeader, opts.languages, json, this);
}
}
catch (error) {
this.emit('error', `Failed to read component file: ${error}`);
}
}
this.queue(file);
});
}
const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench', extensionsProject = 'vscode-extensions', setupProject = 'vscode-setup', serverProject = 'vscode-server';
function getResource(sourceFile) {
let resource;
if (/^vs\/platform/.test(sourceFile)) {
return { name: 'vs/platform', project: editorProject };
}
else if (/^vs\/editor\/contrib/.test(sourceFile)) {
return { name: 'vs/editor/contrib', project: editorProject };
}
else if (/^vs\/editor/.test(sourceFile)) {
return { name: 'vs/editor', project: editorProject };
}
else if (/^vs\/base/.test(sourceFile)) {
return { name: 'vs/base', project: editorProject };
}
else if (/^vs\/code/.test(sourceFile)) {
return { name: 'vs/code', project: workbenchProject };
}
else if (/^vs\/server/.test(sourceFile)) {
return { name: 'vs/server', project: serverProject };
}
else if (/^vs\/workbench\/contrib/.test(sourceFile)) {
resource = sourceFile.split('/', 4).join('/');
return { name: resource, project: workbenchProject };
}
else if (/^vs\/workbench\/services/.test(sourceFile)) {
resource = sourceFile.split('/', 4).join('/');
return { name: resource, project: workbenchProject };
}
else if (/^vs\/workbench/.test(sourceFile)) {
return { name: 'vs/workbench', project: workbenchProject };
}
throw new Error(`Could not identify the XLF bundle for ${sourceFile}`);
}
function createXlfFilesForCoreBundle() {
return (0, event_stream_1.through)(function (file) {
const basename = path_1.default.basename(file.path);
if (basename === 'nls.metadata.json') {
if (file.isBuffer()) {
const xlfs = Object.create(null);
const json = JSON.parse(file.contents.toString('utf8'));
for (const coreModule in json.keys) {
const projectResource = getResource(coreModule);
const resource = projectResource.name;
const project = projectResource.project;
const keys = json.keys[coreModule];
const messages = json.messages[coreModule];
if (keys.length !== messages.length) {
this.emit('error', `There is a mismatch between keys and messages in ${file.relative} for module ${coreModule}`);
return;
}
else {
let xlf = xlfs[resource];
if (!xlf) {
xlf = new XLF(project);
xlfs[resource] = xlf;
}
xlf.addFile(`src/${coreModule}`, keys, messages);
}
}
for (const resource in xlfs) {
const xlf = xlfs[resource];
const filePath = `${xlf.project}/${resource.replace(/\//g, '_')}.xlf`;
const xlfFile = new vinyl_1.default({
path: filePath,
contents: Buffer.from(xlf.toString(), 'utf8')
});
this.queue(xlfFile);
}
}
else {
this.emit('error', new Error(`File ${file.relative} is not using a buffer content`));
return;
}
}
else {
this.emit('error', new Error(`File ${file.relative} is not a core meta data file.`));
return;
}
});
}
function createL10nBundleForExtension(extensionFolderName, prefixWithBuildFolder) {
const prefix = prefixWithBuildFolder ? '.build/' : '';
return gulp_1.default
.src([
// For source code of extensions
`${prefix}extensions/${extensionFolderName}/{src,client,server}/**/*.{ts,tsx}`,
// // For any dependencies pulled in (think vscode-css-languageservice or @vscode/emmet-helper)
`${prefix}extensions/${extensionFolderName}/**/node_modules/{@vscode,vscode-*}/**/*.{js,jsx}`,
// // For any dependencies pulled in that bundle @vscode/l10n. They needed to export the bundle
`${prefix}extensions/${extensionFolderName}/**/bundle.l10n.json`,
])
.pipe((0, event_stream_1.map)(function (data, callback) {
const file = data;
if (!file.isBuffer()) {
// Not a buffer so we drop it
callback();
return;
}
const extension = path_1.default.extname(file.relative);
if (extension !== '.json') {
const contents = file.contents.toString('utf8');
(0, l10n_dev_1.getL10nJson)([{ contents, extension }])
.then((json) => {
callback(undefined, new vinyl_1.default({
path: `extensions/${extensionFolderName}/bundle.l10n.json`,
contents: Buffer.from(JSON.stringify(json), 'utf8')
}));
})
.catch((err) => {
callback(new Error(`File ${file.relative} threw an error when parsing: ${err}`));
});
// signal pause?
return false;
}
// for bundle.l10n.jsons
let bundleJson;
try {
bundleJson = JSON.parse(file.contents.toString('utf8'));
}
catch (err) {
callback(new Error(`File ${file.relative} threw an error when parsing: ${err}`));
return;
}
// some validation of the bundle.l10n.json format
for (const key in bundleJson) {
if (typeof bundleJson[key] !== 'string' &&
(typeof bundleJson[key].message !== 'string' || !Array.isArray(bundleJson[key].comment))) {
callback(new Error(`Invalid bundle.l10n.json file. The value for key ${key} is not in the expected format.`));
return;
}
}
callback(undefined, file);
}))
.pipe((0, gulp_merge_json_1.default)({
fileName: `extensions/${extensionFolderName}/bundle.l10n.json`,
jsonSpace: '',
concatArrays: true
}));
}
exports.EXTERNAL_EXTENSIONS = [
'ms-vscode.js-debug',
'ms-vscode.js-debug-companion',
'ms-vscode.vscode-js-profile-table',
];
function createXlfFilesForExtensions() {
let counter = 0;
let folderStreamEnded = false;
let folderStreamEndEmitted = false;
return (0, event_stream_1.through)(function (extensionFolder) {
const folderStream = this;
const stat = fs_1.default.statSync(extensionFolder.path);
if (!stat.isDirectory()) {
return;
}
const extensionFolderName = path_1.default.basename(extensionFolder.path);
if (extensionFolderName === 'node_modules') {
return;
}
// Get extension id and use that as the id
const manifest = fs_1.default.readFileSync(path_1.default.join(extensionFolder.path, 'package.json'), 'utf-8');
const manifestJson = JSON.parse(manifest);
const extensionId = manifestJson.publisher + '.' + manifestJson.name;
counter++;
let _l10nMap;
function getL10nMap() {
if (!_l10nMap) {
_l10nMap = new Map();
}
return _l10nMap;
}
(0, event_stream_1.merge)(gulp_1.default.src([`.build/extensions/${extensionFolderName}/package.nls.json`, `.build/extensions/${extensionFolderName}/**/nls.metadata.json`], { allowEmpty: true }), createL10nBundleForExtension(extensionFolderName, exports.EXTERNAL_EXTENSIONS.includes(extensionId))).pipe((0, event_stream_1.through)(function (file) {
if (file.isBuffer()) {
const buffer = file.contents;
const basename = path_1.default.basename(file.path);
if (basename === 'package.nls.json') {
const json = JSON.parse(buffer.toString('utf8'));
getL10nMap().set(`extensions/${extensionId}/package`, json);
}
else if (basename === 'nls.metadata.json') {
const json = JSON.parse(buffer.toString('utf8'));
const relPath = path_1.default.relative(`.build/extensions/${extensionFolderName}`, path_1.default.dirname(file.path));
for (const file in json) {
const fileContent = json[file];
const info = Object.create(null);
for (let i = 0; i < fileContent.messages.length; i++) {
const message = fileContent.messages[i];
const { key, comment } = LocalizeInfo.is(fileContent.keys[i])
? fileContent.keys[i]
: { key: fileContent.keys[i], comment: undefined };
info[key] = comment ? { message, comment } : message;
}
getL10nMap().set(`extensions/${extensionId}/${relPath}/${file}`, info);
}
}
else if (basename === 'bundle.l10n.json') {
const json = JSON.parse(buffer.toString('utf8'));
getL10nMap().set(`extensions/${extensionId}/bundle`, json);
}
else {
this.emit('error', new Error(`${file.path} is not a valid extension nls file`));
return;
}
}
}, function () {
if (_l10nMap?.size > 0) {
const xlfFile = new vinyl_1.default({
path: path_1.default.join(extensionsProject, extensionId + '.xlf'),
contents: Buffer.from((0, l10n_dev_1.getL10nXlf)(_l10nMap), 'utf8')
});
folderStream.queue(xlfFile);
}
this.queue(null);
counter--;
if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) {
folderStreamEndEmitted = true;
folderStream.queue(null);
}
}));
}, function () {
folderStreamEnded = true;
if (counter === 0) {
folderStreamEndEmitted = true;
this.queue(null);
}
});
}
function createXlfFilesForIsl() {
return (0, event_stream_1.through)(function (file) {
let projectName, resourceFile;
if (path_1.default.basename(file.path) === 'messages.en.isl') {
projectName = setupProject;
resourceFile = 'messages.xlf';
}
else {
throw new Error(`Unknown input file ${file.path}`);
}
const xlf = new XLF(projectName), keys = [], messages = [];
const model = new TextModel(file.contents.toString());
let inMessageSection = false;
model.lines.forEach(line => {
if (line.length === 0) {
return;
}
const firstChar = line.charAt(0);
switch (firstChar) {
case ';':
// Comment line;
return;
case '[':
inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
return;
}
if (!inMessageSection) {
return;
}
const sections = line.split('=');
if (sections.length !== 2) {
throw new Error(`Badly formatted message found: ${line}`);
}
else {
const key = sections[0];
const value = sections[1];
if (key.length > 0 && value.length > 0) {
keys.push(key);
messages.push(value);
}
}
});
const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
xlf.addFile(originalPath, keys, messages);
// Emit only upon all ISL files combined into single XLF instance
const newFilePath = path_1.default.join(projectName, resourceFile);
const xlfFile = new vinyl_1.default({ path: newFilePath, contents: Buffer.from(xlf.toString(), 'utf-8') });
this.queue(xlfFile);
});
}
function createI18nFile(name, messages) {
const result = Object.create(null);
result[''] = [
'--------------------------------------------------------------------------------------------',
'Copyright (c) Microsoft Corporation. All rights reserved.',
'Licensed under the MIT License. See License.txt in the project root for license information.',
'--------------------------------------------------------------------------------------------',
'Do not edit this file. It is machine generated.'
];
for (const key of Object.keys(messages)) {
result[key] = messages[key];
}
let content = JSON.stringify(result, null, '\t');
if (process.platform === 'win32') {
content = content.replace(/\n/g, '\r\n');
}
return new vinyl_1.default({
path: path_1.default.join(name + '.i18n.json'),
contents: Buffer.from(content, 'utf8')
});
}
const i18nPackVersion = '1.0.0';
function getRecordFromL10nJsonFormat(l10nJsonFormat) {
const record = {};
for (const key of Object.keys(l10nJsonFormat).sort()) {
const value = l10nJsonFormat[key];
record[key] = typeof value === 'string' ? value : value.message;
}
return record;
}
function prepareI18nPackFiles(resultingTranslationPaths) {
const parsePromises = [];
const mainPack = { version: i18nPackVersion, contents: {} };
const extensionsPacks = {};
const errors = [];
return (0, event_stream_1.through)(function (xlf) {
let project = path_1.default.basename(path_1.default.dirname(path_1.default.dirname(xlf.relative)));
// strip `-new` since vscode-extensions-loc uses the `-new` suffix to indicate that it's from the new loc pipeline
const resource = path_1.default.basename(path_1.default.basename(xlf.relative, '.xlf'), '-new');
if (exports.EXTERNAL_EXTENSIONS.find(e => e === resource)) {
project = extensionsProject;
}
const contents = xlf.contents.toString();
log(`Found ${project}: ${resource}`);
const parsePromise = (0, l10n_dev_1.getL10nFilesFromXlf)(contents);
parsePromises.push(parsePromise);
parsePromise.then(resolvedFiles => {
resolvedFiles.forEach(file => {
const path = file.name;
const firstSlash = path.indexOf('/');
if (project === extensionsProject) {
// resource will be the extension id
let extPack = extensionsPacks[resource];
if (!extPack) {
extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} };
}
// remove 'extensions/extensionId/' segment
const secondSlash = path.indexOf('/', firstSlash + 1);
extPack.contents[path.substring(secondSlash + 1)] = getRecordFromL10nJsonFormat(file.messages);
}
else {
mainPack.contents[path.substring(firstSlash + 1)] = getRecordFromL10nJsonFormat(file.messages);
}
});
}).catch(reason => {
errors.push(reason);
});
}, function () {
Promise.all(parsePromises)
.then(() => {
if (errors.length > 0) {
throw errors;
}
const translatedMainFile = createI18nFile('./main', mainPack);
resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' });
this.queue(translatedMainFile);
for (const extensionId in extensionsPacks) {
const translatedExtFile = createI18nFile(`extensions/${extensionId}`, extensionsPacks[extensionId]);
this.queue(translatedExtFile);
resultingTranslationPaths.push({ id: extensionId, resourceName: `extensions/${extensionId}.i18n.json` });
}
this.queue(null);
})
.catch((reason) => {
this.emit('error', reason);
});
});
}
function prepareIslFiles(language, innoSetupConfig) {
const parsePromises = [];
return (0, event_stream_1.through)(function (xlf) {
const stream = this;
const parsePromise = XLF.parse(xlf.contents.toString());
parsePromises.push(parsePromise);
parsePromise.then(resolvedFiles => {
resolvedFiles.forEach(file => {
const translatedFile = createIslFile(file.name, file.messages, language, innoSetupConfig);
stream.queue(translatedFile);
});
}).catch(reason => {
this.emit('error', reason);
});
}, function () {
Promise.all(parsePromises)
.then(() => { this.queue(null); })
.catch(reason => {
this.emit('error', reason);
});
});
}
function createIslFile(name, messages, language, innoSetup) {
const content = [];
let originalContent;
if (path_1.default.basename(name) === 'Default') {
originalContent = new TextModel(fs_1.default.readFileSync(name + '.isl', 'utf8'));
}
else {
originalContent = new TextModel(fs_1.default.readFileSync(name + '.en.isl', 'utf8'));
}
originalContent.lines.forEach(line => {
if (line.length > 0) {
const firstChar = line.charAt(0);
if (firstChar === '[' || firstChar === ';') {
content.push(line);
}
else {
const sections = line.split('=');
const key = sections[0];
let translated = line;
if (key) {
const translatedMessage = messages[key];
if (translatedMessage) {
translated = `${key}=${translatedMessage}`;
}
}
content.push(translated);
}
}
});
const basename = path_1.default.basename(name);
const filePath = `${basename}.${language.id}.isl`;
const encoded = iconv_lite_umd_1.default.encode(Buffer.from(content.join('\r\n'), 'utf8').toString(), innoSetup.codePage);
return new vinyl_1.default({
path: filePath,
contents: Buffer.from(encoded),
});
}
function encodeEntities(value) {
const result = [];
for (let i = 0; i < value.length; i++) {
const ch = value[i];
switch (ch) {
case '<':
result.push('<');
break;
case '>':
result.push('>');
break;
case '&':
result.push('&');
break;
default:
result.push(ch);
}
}
return result.join('');
}
function decodeEntities(value) {
return value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
}
//# sourceMappingURL=i18n.js.map
================================================
FILE: build/lib/i18n.resources.json
================================================
{
"editor": [
{
"name": "vs/platform",
"project": "vscode-editor"
},
{
"name": "vs/editor/contrib",
"project": "vscode-editor"
},
{
"name": "vs/editor",
"project": "vscode-editor"
},
{
"name": "vs/base",
"project": "vscode-editor"
}
],
"workbench": [
{
"name": "vs/code",
"project": "vscode-workbench"
},
{
"name": "vs/workbench",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/api/common",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/bulkEdit",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/cli",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/codeEditor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/callHierarchy",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/typeHierarchy",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/codeActions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/commands",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/markdown",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/comments",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/debug",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/dialogs",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/multiDiffEditor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/emmet",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/assignment",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/auxiliaryWindow",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/extensions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/externalTerminal",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/files",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/folding",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/html",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/issue",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/inlayHints",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/interactive",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/languageStatus",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/limitIndicator",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/keybindings",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/markers",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/mergeEditor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/localization",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/logs",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/output",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/performance",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/preferences",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/notebook",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/inlineChat",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/chat",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/quickaccess",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/userData",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/remote",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/relauncher",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/sash",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/scm",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/search",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/searchEditor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/snippets",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/format",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/tags",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/speech",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/surveys",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/tasks",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/testing",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/terminal",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/terminalContrib",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/themes",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/trust",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/update",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/url",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/watermark",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/webview",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/webviewPanel",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/workspace",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/workspaces",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/customEditor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/externalUriOpener",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomeGettingStarted",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomePage",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomeViews",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomeWalkthrough",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomeDialog",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/outline",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/userDataSync",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/editSessions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/views",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/languageDetection",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/accessibilitySignals",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/deprecatedExtensionMigrator",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/bracketPairColorizer2Telemetry",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/scrollLocking",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/remoteTunnel",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/actions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/authToken",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/backup",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/bulkEdit",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/clipboard",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/commands",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/configuration",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/configurationResolver",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/dialogs",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/editor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/extensions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/extensionManagement",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/files",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/filesConfiguration",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/history",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/hover",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/log",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/integrity",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/keybinding",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/lifecycle",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/language",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/progress",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/remote",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/search",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/suggest",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/textfile",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/themes",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/textMate",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/workingCopy",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/workspaces",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/decorations",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/label",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/preferences",
"project": "vscode-preferences"
},
{
"name": "vs/workbench/services/notification",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/userData",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/userDataSync",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/editSessions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/views",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/timeline",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/localHistory",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/authentication",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/extensionRecommendations",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/gettingStarted",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/host",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/userDataProfile",
"project": "vscode-profiles"
},
{
"name": "vs/workbench/services/userDataProfile",
"project": "vscode-profiles"
},
{
"name": "vs/workbench/services/localization",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/share",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/accessibility",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/issue",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/secrets",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/accountEntitlements",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/authentication",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/replNotebook",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/list",
"project": "vscode-workbench"
}
]
}
================================================
FILE: build/lib/i18n.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import path from 'path';
import fs from 'fs';
import { map, merge, through, ThroughStream } from 'event-stream';
import jsonMerge from 'gulp-merge-json';
import File from 'vinyl';
import xml2js from 'xml2js';
import gulp from 'gulp';
import fancyLog from 'fancy-log';
import ansiColors from 'ansi-colors';
import iconv from '@vscode/iconv-lite-umd';
import { l10nJsonFormat, getL10nXlf, l10nJsonDetails, getL10nFilesFromXlf, getL10nJson } from '@vscode/l10n-dev';
const REPO_ROOT_PATH = path.join(__dirname, '../..');
function log(message: any, ...rest: any[]): void {
fancyLog(ansiColors.green('[i18n]'), message, ...rest);
}
export interface Language {
id: string; // language id, e.g. zh-tw, de
translationId?: string; // language id used in translation tools, e.g. zh-hant, de (optional, if not set, the id is used)
folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used)
}
export interface InnoSetup {
codePage: string; //code page for encoding (http://www.jrsoftware.org/ishelp/index.php?topic=langoptionssection)
}
export const defaultLanguages: Language[] = [
{ id: 'zh-tw', folderName: 'cht', translationId: 'zh-hant' },
{ id: 'zh-cn', folderName: 'chs', translationId: 'zh-hans' },
{ id: 'ja', folderName: 'jpn' },
{ id: 'ko', folderName: 'kor' },
{ id: 'de', folderName: 'deu' },
{ id: 'fr', folderName: 'fra' },
{ id: 'es', folderName: 'esn' },
{ id: 'ru', folderName: 'rus' },
{ id: 'it', folderName: 'ita' }
];
// languages requested by the community to non-stable builds
export const extraLanguages: Language[] = [
{ id: 'pt-br', folderName: 'ptb' },
{ id: 'hu', folderName: 'hun' },
{ id: 'tr', folderName: 'trk' }
];
interface Item {
id: string;
message: string;
comment?: string;
}
export interface Resource {
name: string;
project: string;
}
interface LocalizeInfo {
key: string;
comment: string[];
}
module LocalizeInfo {
export function is(value: any): value is LocalizeInfo {
const candidate = value as LocalizeInfo;
return candidate && typeof candidate.key === 'string' && (candidate.comment === undefined || (Array.isArray(candidate.comment) && candidate.comment.every(element => typeof element === 'string')));
}
}
interface BundledFormat {
keys: Record;
messages: Record;
bundles: Record;
}
module BundledFormat {
export function is(value: any): value is BundledFormat {
if (value === undefined) {
return false;
}
const candidate = value as BundledFormat;
const length = Object.keys(value).length;
return length === 3 && !!candidate.keys && !!candidate.messages && !!candidate.bundles;
}
}
type NLSKeysFormat = [string /* module ID */, string[] /* keys */];
module NLSKeysFormat {
export function is(value: any): value is NLSKeysFormat {
if (value === undefined) {
return false;
}
const candidate = value as NLSKeysFormat;
return Array.isArray(candidate) && Array.isArray(candidate[1]);
}
}
interface BundledExtensionFormat {
[key: string]: {
messages: string[];
keys: (string | LocalizeInfo)[];
};
}
interface I18nFormat {
version: string;
contents: {
[module: string]: {
[messageKey: string]: string;
};
};
}
export class Line {
private buffer: string[] = [];
constructor(indent: number = 0) {
if (indent > 0) {
this.buffer.push(new Array(indent + 1).join(' '));
}
}
public append(value: string): Line {
this.buffer.push(value);
return this;
}
public toString(): string {
return this.buffer.join('');
}
}
class TextModel {
private _lines: string[];
constructor(contents: string) {
this._lines = contents.split(/\r\n|\r|\n/);
}
public get lines(): string[] {
return this._lines;
}
}
export class XLF {
private buffer: string[];
private files: Record;
public numberOfMessages: number;
constructor(public project: string) {
this.buffer = [];
this.files = Object.create(null);
this.numberOfMessages = 0;
}
public toString(): string {
this.appendHeader();
const files = Object.keys(this.files).sort();
for (const file of files) {
this.appendNewLine(``, 2);
const items = this.files[file].sort((a: Item, b: Item) => {
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
for (const item of items) {
this.addStringItem(file, item);
}
this.appendNewLine('');
}
this.appendFooter();
return this.buffer.join('\r\n');
}
public addFile(original: string, keys: (string | LocalizeInfo)[], messages: string[]) {
if (keys.length === 0) {
console.log('No keys in ' + original);
return;
}
if (keys.length !== messages.length) {
throw new Error(`Unmatching keys(${keys.length}) and messages(${messages.length}).`);
}
this.numberOfMessages += keys.length;
this.files[original] = [];
const existingKeys = new Set();
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
let realKey: string | undefined;
let comment: string | undefined;
if (typeof key === 'string') {
realKey = key;
comment = undefined;
} else if (LocalizeInfo.is(key)) {
realKey = key.key;
if (key.comment && key.comment.length > 0) {
comment = key.comment.map(comment => encodeEntities(comment)).join('\r\n');
}
}
if (!realKey || existingKeys.has(realKey)) {
continue;
}
existingKeys.add(realKey);
const message: string = encodeEntities(messages[i]);
this.files[original].push({ id: realKey, message: message, comment: comment });
}
}
private addStringItem(file: string, item: Item): void {
if (!item.id || item.message === undefined || item.message === null) {
throw new Error(`No item ID or value specified: ${JSON.stringify(item)}. File: ${file}`);
}
if (item.message.length === 0) {
log(`Item with id ${item.id} in file ${file} has an empty message.`);
}
this.appendNewLine(``, 4);
this.appendNewLine(`${item.message}`, 6);
if (item.comment) {
this.appendNewLine(`${item.comment}`, 6);
}
this.appendNewLine('', 4);
}
private appendHeader(): void {
this.appendNewLine('', 0);
this.appendNewLine('', 0);
}
private appendFooter(): void {
this.appendNewLine('', 0);
}
private appendNewLine(content: string, indent?: number): void {
const line = new Line(indent);
line.append(content);
this.buffer.push(line.toString());
}
static parse = function (xlfString: string): Promise {
return new Promise((resolve, reject) => {
const parser = new xml2js.Parser();
const files: { messages: Record; name: string; language: string }[] = [];
parser.parseString(xlfString, function (err: any, result: any) {
if (err) {
reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`));
}
const fileNodes: any[] = result['xliff']['file'];
if (!fileNodes) {
reject(new Error(`XLF parsing error: XLIFF file does not contain "xliff" or "file" node(s) required for parsing.`));
}
fileNodes.forEach((file) => {
const name = file.$.original;
if (!name) {
reject(new Error(`XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file.`));
}
const language = file.$['target-language'];
if (!language) {
reject(new Error(`XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.`));
}
const messages: Record = {};
const transUnits = file.body[0]['trans-unit'];
if (transUnits) {
transUnits.forEach((unit: any) => {
const key = unit.$.id;
if (!unit.target) {
return; // No translation available
}
let val = unit.target[0];
if (typeof val !== 'string') {
// We allow empty source values so support them for translations as well.
val = val._ ? val._ : '';
}
if (!key) {
reject(new Error(`XLF parsing error: trans-unit ${JSON.stringify(unit, undefined, 0)} defined in file ${name} is missing the ID attribute.`));
return;
}
messages[key] = decodeEntities(val);
});
files.push({ messages, name, language: language.toLowerCase() });
}
});
resolve(files);
});
});
};
}
function sortLanguages(languages: Language[]): Language[] {
return languages.sort((a: Language, b: Language): number => {
return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
});
}
function stripComments(content: string): string {
// Copied from stripComments.js
//
// First group matches a double quoted string
// Second group matches a single quoted string
// Third group matches a multi line comment
// Forth group matches a single line comment
// Fifth group matches a trailing comma
const regexp = /("[^"\\]*(?:\\.[^"\\]*)*")|('[^'\\]*(?:\\.[^'\\]*)*')|(\/\*[^\/\*]*(?:(?:\*|\/)[^\/\*]*)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))|(,\s*[}\]])/g;
const result = content.replace(regexp, (match, _m1: string, _m2: string, m3: string, m4: string, m5: string) => {
// Only one of m1, m2, m3, m4, m5 matches
if (m3) {
// A block comment. Replace with nothing
return '';
} else if (m4) {
// Since m4 is a single line comment is is at least of length 2 (e.g. //)
// If it ends in \r?\n then keep it.
const length = m4.length;
if (m4[length - 1] === '\n') {
return m4[length - 2] === '\r' ? '\r\n' : '\n';
} else {
return '';
}
} else if (m5) {
// Remove the trailing comma
return match.substring(1);
} else {
// We match a string
return match;
}
});
return result;
}
function processCoreBundleFormat(base: string, fileHeader: string, languages: Language[], json: NLSKeysFormat, emitter: ThroughStream) {
const languageDirectory = path.join(REPO_ROOT_PATH, '..', 'vscode-loc', 'i18n');
if (!fs.existsSync(languageDirectory)) {
log(`No VS Code localization repository found. Looking at ${languageDirectory}`);
log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`);
}
const sortedLanguages = sortLanguages(languages);
sortedLanguages.forEach((language) => {
if (process.env['VSCODE_BUILD_VERBOSE']) {
log(`Generating nls bundles for: ${language.id}`);
}
const languageFolderName = language.translationId || language.id;
const i18nFile = path.join(languageDirectory, `vscode-language-pack-${languageFolderName}`, 'translations', 'main.i18n.json');
let allMessages: I18nFormat | undefined;
if (fs.existsSync(i18nFile)) {
const content = stripComments(fs.readFileSync(i18nFile, 'utf8'));
allMessages = JSON.parse(content);
}
let nlsIndex = 0;
const nlsResult: Array = [];
for (const [moduleId, nlsKeys] of json) {
const moduleTranslations = allMessages?.contents[moduleId];
for (const nlsKey of nlsKeys) {
nlsResult.push(moduleTranslations?.[nlsKey]); // pushing `undefined` is fine, as we keep english strings as fallback for monaco editor in the build
nlsIndex++;
}
}
emitter.queue(new File({
contents: Buffer.from(`${fileHeader}
globalThis._VSCODE_NLS_MESSAGES=${JSON.stringify(nlsResult)};
globalThis._VSCODE_NLS_LANGUAGE=${JSON.stringify(language.id)};`),
base,
path: `${base}/nls.messages.${language.id}.js`
}));
});
}
export function processNlsFiles(opts: { out: string; fileHeader: string; languages: Language[] }): ThroughStream {
return through(function (this: ThroughStream, file: File) {
const fileName = path.basename(file.path);
if (fileName === 'nls.keys.json') {
try {
const contents = file.contents.toString('utf8');
const json = JSON.parse(contents);
if (NLSKeysFormat.is(json)) {
processCoreBundleFormat(file.base, opts.fileHeader, opts.languages, json, this);
}
} catch (error) {
this.emit('error', `Failed to read component file: ${error}`);
}
}
this.queue(file);
});
}
const editorProject: string = 'vscode-editor',
workbenchProject: string = 'vscode-workbench',
extensionsProject: string = 'vscode-extensions',
setupProject: string = 'vscode-setup',
serverProject: string = 'vscode-server';
export function getResource(sourceFile: string): Resource {
let resource: string;
if (/^vs\/platform/.test(sourceFile)) {
return { name: 'vs/platform', project: editorProject };
} else if (/^vs\/editor\/contrib/.test(sourceFile)) {
return { name: 'vs/editor/contrib', project: editorProject };
} else if (/^vs\/editor/.test(sourceFile)) {
return { name: 'vs/editor', project: editorProject };
} else if (/^vs\/base/.test(sourceFile)) {
return { name: 'vs/base', project: editorProject };
} else if (/^vs\/code/.test(sourceFile)) {
return { name: 'vs/code', project: workbenchProject };
} else if (/^vs\/server/.test(sourceFile)) {
return { name: 'vs/server', project: serverProject };
} else if (/^vs\/workbench\/contrib/.test(sourceFile)) {
resource = sourceFile.split('/', 4).join('/');
return { name: resource, project: workbenchProject };
} else if (/^vs\/workbench\/services/.test(sourceFile)) {
resource = sourceFile.split('/', 4).join('/');
return { name: resource, project: workbenchProject };
} else if (/^vs\/workbench/.test(sourceFile)) {
return { name: 'vs/workbench', project: workbenchProject };
}
throw new Error(`Could not identify the XLF bundle for ${sourceFile}`);
}
export function createXlfFilesForCoreBundle(): ThroughStream {
return through(function (this: ThroughStream, file: File) {
const basename = path.basename(file.path);
if (basename === 'nls.metadata.json') {
if (file.isBuffer()) {
const xlfs: Record = Object.create(null);
const json: BundledFormat = JSON.parse((file.contents as Buffer).toString('utf8'));
for (const coreModule in json.keys) {
const projectResource = getResource(coreModule);
const resource = projectResource.name;
const project = projectResource.project;
const keys = json.keys[coreModule];
const messages = json.messages[coreModule];
if (keys.length !== messages.length) {
this.emit('error', `There is a mismatch between keys and messages in ${file.relative} for module ${coreModule}`);
return;
} else {
let xlf = xlfs[resource];
if (!xlf) {
xlf = new XLF(project);
xlfs[resource] = xlf;
}
xlf.addFile(`src/${coreModule}`, keys, messages);
}
}
for (const resource in xlfs) {
const xlf = xlfs[resource];
const filePath = `${xlf.project}/${resource.replace(/\//g, '_')}.xlf`;
const xlfFile = new File({
path: filePath,
contents: Buffer.from(xlf.toString(), 'utf8')
});
this.queue(xlfFile);
}
} else {
this.emit('error', new Error(`File ${file.relative} is not using a buffer content`));
return;
}
} else {
this.emit('error', new Error(`File ${file.relative} is not a core meta data file.`));
return;
}
});
}
function createL10nBundleForExtension(extensionFolderName: string, prefixWithBuildFolder: boolean): NodeJS.ReadWriteStream {
const prefix = prefixWithBuildFolder ? '.build/' : '';
return gulp
.src([
// For source code of extensions
`${prefix}extensions/${extensionFolderName}/{src,client,server}/**/*.{ts,tsx}`,
// // For any dependencies pulled in (think vscode-css-languageservice or @vscode/emmet-helper)
`${prefix}extensions/${extensionFolderName}/**/node_modules/{@vscode,vscode-*}/**/*.{js,jsx}`,
// // For any dependencies pulled in that bundle @vscode/l10n. They needed to export the bundle
`${prefix}extensions/${extensionFolderName}/**/bundle.l10n.json`,
])
.pipe(map(function (data, callback) {
const file = data as File;
if (!file.isBuffer()) {
// Not a buffer so we drop it
callback();
return;
}
const extension = path.extname(file.relative);
if (extension !== '.json') {
const contents = file.contents.toString('utf8');
getL10nJson([{ contents, extension }])
.then((json) => {
callback(undefined, new File({
path: `extensions/${extensionFolderName}/bundle.l10n.json`,
contents: Buffer.from(JSON.stringify(json), 'utf8')
}));
})
.catch((err) => {
callback(new Error(`File ${file.relative} threw an error when parsing: ${err}`));
});
// signal pause?
return false;
}
// for bundle.l10n.jsons
let bundleJson;
try {
bundleJson = JSON.parse(file.contents.toString('utf8'));
} catch (err) {
callback(new Error(`File ${file.relative} threw an error when parsing: ${err}`));
return;
}
// some validation of the bundle.l10n.json format
for (const key in bundleJson) {
if (
typeof bundleJson[key] !== 'string' &&
(typeof bundleJson[key].message !== 'string' || !Array.isArray(bundleJson[key].comment))
) {
callback(new Error(`Invalid bundle.l10n.json file. The value for key ${key} is not in the expected format.`));
return;
}
}
callback(undefined, file);
}))
.pipe(jsonMerge({
fileName: `extensions/${extensionFolderName}/bundle.l10n.json`,
jsonSpace: '',
concatArrays: true
}));
}
export const EXTERNAL_EXTENSIONS = [
'ms-vscode.js-debug',
'ms-vscode.js-debug-companion',
'ms-vscode.vscode-js-profile-table',
];
export function createXlfFilesForExtensions(): ThroughStream {
let counter: number = 0;
let folderStreamEnded: boolean = false;
let folderStreamEndEmitted: boolean = false;
return through(function (this: ThroughStream, extensionFolder: File) {
const folderStream = this;
const stat = fs.statSync(extensionFolder.path);
if (!stat.isDirectory()) {
return;
}
const extensionFolderName = path.basename(extensionFolder.path);
if (extensionFolderName === 'node_modules') {
return;
}
// Get extension id and use that as the id
const manifest = fs.readFileSync(path.join(extensionFolder.path, 'package.json'), 'utf-8');
const manifestJson = JSON.parse(manifest);
const extensionId = manifestJson.publisher + '.' + manifestJson.name;
counter++;
let _l10nMap: Map;
function getL10nMap() {
if (!_l10nMap) {
_l10nMap = new Map();
}
return _l10nMap;
}
merge(
gulp.src([`.build/extensions/${extensionFolderName}/package.nls.json`, `.build/extensions/${extensionFolderName}/**/nls.metadata.json`], { allowEmpty: true }),
createL10nBundleForExtension(extensionFolderName, EXTERNAL_EXTENSIONS.includes(extensionId))
).pipe(through(function (file: File) {
if (file.isBuffer()) {
const buffer: Buffer = file.contents as Buffer;
const basename = path.basename(file.path);
if (basename === 'package.nls.json') {
const json: l10nJsonFormat = JSON.parse(buffer.toString('utf8'));
getL10nMap().set(`extensions/${extensionId}/package`, json);
} else if (basename === 'nls.metadata.json') {
const json: BundledExtensionFormat = JSON.parse(buffer.toString('utf8'));
const relPath = path.relative(`.build/extensions/${extensionFolderName}`, path.dirname(file.path));
for (const file in json) {
const fileContent = json[file];
const info: l10nJsonFormat = Object.create(null);
for (let i = 0; i < fileContent.messages.length; i++) {
const message = fileContent.messages[i];
const { key, comment } = LocalizeInfo.is(fileContent.keys[i])
? fileContent.keys[i] as LocalizeInfo
: { key: fileContent.keys[i] as string, comment: undefined };
info[key] = comment ? { message, comment } : message;
}
getL10nMap().set(`extensions/${extensionId}/${relPath}/${file}`, info);
}
} else if (basename === 'bundle.l10n.json') {
const json: l10nJsonFormat = JSON.parse(buffer.toString('utf8'));
getL10nMap().set(`extensions/${extensionId}/bundle`, json);
} else {
this.emit('error', new Error(`${file.path} is not a valid extension nls file`));
return;
}
}
}, function () {
if (_l10nMap?.size > 0) {
const xlfFile = new File({
path: path.join(extensionsProject, extensionId + '.xlf'),
contents: Buffer.from(getL10nXlf(_l10nMap), 'utf8')
});
folderStream.queue(xlfFile);
}
this.queue(null);
counter--;
if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) {
folderStreamEndEmitted = true;
folderStream.queue(null);
}
}));
}, function () {
folderStreamEnded = true;
if (counter === 0) {
folderStreamEndEmitted = true;
this.queue(null);
}
});
}
export function createXlfFilesForIsl(): ThroughStream {
return through(function (this: ThroughStream, file: File) {
let projectName: string,
resourceFile: string;
if (path.basename(file.path) === 'messages.en.isl') {
projectName = setupProject;
resourceFile = 'messages.xlf';
} else {
throw new Error(`Unknown input file ${file.path}`);
}
const xlf = new XLF(projectName),
keys: string[] = [],
messages: string[] = [];
const model = new TextModel(file.contents.toString());
let inMessageSection = false;
model.lines.forEach(line => {
if (line.length === 0) {
return;
}
const firstChar = line.charAt(0);
switch (firstChar) {
case ';':
// Comment line;
return;
case '[':
inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
return;
}
if (!inMessageSection) {
return;
}
const sections: string[] = line.split('=');
if (sections.length !== 2) {
throw new Error(`Badly formatted message found: ${line}`);
} else {
const key = sections[0];
const value = sections[1];
if (key.length > 0 && value.length > 0) {
keys.push(key);
messages.push(value);
}
}
});
const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
xlf.addFile(originalPath, keys, messages);
// Emit only upon all ISL files combined into single XLF instance
const newFilePath = path.join(projectName, resourceFile);
const xlfFile = new File({ path: newFilePath, contents: Buffer.from(xlf.toString(), 'utf-8') });
this.queue(xlfFile);
});
}
function createI18nFile(name: string, messages: any): File {
const result = Object.create(null);
result[''] = [
'--------------------------------------------------------------------------------------------',
'Copyright (c) Microsoft Corporation. All rights reserved.',
'Licensed under the MIT License. See License.txt in the project root for license information.',
'--------------------------------------------------------------------------------------------',
'Do not edit this file. It is machine generated.'
];
for (const key of Object.keys(messages)) {
result[key] = messages[key];
}
let content = JSON.stringify(result, null, '\t');
if (process.platform === 'win32') {
content = content.replace(/\n/g, '\r\n');
}
return new File({
path: path.join(name + '.i18n.json'),
contents: Buffer.from(content, 'utf8')
});
}
interface I18nPack {
version: string;
contents: {
[path: string]: Record;
};
}
const i18nPackVersion = '1.0.0';
export interface TranslationPath {
id: string;
resourceName: string;
}
function getRecordFromL10nJsonFormat(l10nJsonFormat: l10nJsonFormat): Record {
const record: Record = {};
for (const key of Object.keys(l10nJsonFormat).sort()) {
const value = l10nJsonFormat[key];
record[key] = typeof value === 'string' ? value : value.message;
}
return record;
}
export function prepareI18nPackFiles(resultingTranslationPaths: TranslationPath[]): NodeJS.ReadWriteStream {
const parsePromises: Promise[] = [];
const mainPack: I18nPack = { version: i18nPackVersion, contents: {} };
const extensionsPacks: Record = {};
const errors: any[] = [];
return through(function (this: ThroughStream, xlf: File) {
let project = path.basename(path.dirname(path.dirname(xlf.relative)));
// strip `-new` since vscode-extensions-loc uses the `-new` suffix to indicate that it's from the new loc pipeline
const resource = path.basename(path.basename(xlf.relative, '.xlf'), '-new');
if (EXTERNAL_EXTENSIONS.find(e => e === resource)) {
project = extensionsProject;
}
const contents = xlf.contents.toString();
log(`Found ${project}: ${resource}`);
const parsePromise = getL10nFilesFromXlf(contents);
parsePromises.push(parsePromise);
parsePromise.then(
resolvedFiles => {
resolvedFiles.forEach(file => {
const path = file.name;
const firstSlash = path.indexOf('/');
if (project === extensionsProject) {
// resource will be the extension id
let extPack = extensionsPacks[resource];
if (!extPack) {
extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} };
}
// remove 'extensions/extensionId/' segment
const secondSlash = path.indexOf('/', firstSlash + 1);
extPack.contents[path.substring(secondSlash + 1)] = getRecordFromL10nJsonFormat(file.messages);
} else {
mainPack.contents[path.substring(firstSlash + 1)] = getRecordFromL10nJsonFormat(file.messages);
}
});
}
).catch(reason => {
errors.push(reason);
});
}, function () {
Promise.all(parsePromises)
.then(() => {
if (errors.length > 0) {
throw errors;
}
const translatedMainFile = createI18nFile('./main', mainPack);
resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' });
this.queue(translatedMainFile);
for (const extensionId in extensionsPacks) {
const translatedExtFile = createI18nFile(`extensions/${extensionId}`, extensionsPacks[extensionId]);
this.queue(translatedExtFile);
resultingTranslationPaths.push({ id: extensionId, resourceName: `extensions/${extensionId}.i18n.json` });
}
this.queue(null);
})
.catch((reason) => {
this.emit('error', reason);
});
});
}
export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup): ThroughStream {
const parsePromises: Promise[] = [];
return through(function (this: ThroughStream, xlf: File) {
const stream = this;
const parsePromise = XLF.parse(xlf.contents.toString());
parsePromises.push(parsePromise);
parsePromise.then(
resolvedFiles => {
resolvedFiles.forEach(file => {
const translatedFile = createIslFile(file.name, file.messages, language, innoSetupConfig);
stream.queue(translatedFile);
});
}
).catch(reason => {
this.emit('error', reason);
});
}, function () {
Promise.all(parsePromises)
.then(() => { this.queue(null); })
.catch(reason => {
this.emit('error', reason);
});
});
}
function createIslFile(name: string, messages: l10nJsonFormat, language: Language, innoSetup: InnoSetup): File {
const content: string[] = [];
let originalContent: TextModel;
if (path.basename(name) === 'Default') {
originalContent = new TextModel(fs.readFileSync(name + '.isl', 'utf8'));
} else {
originalContent = new TextModel(fs.readFileSync(name + '.en.isl', 'utf8'));
}
originalContent.lines.forEach(line => {
if (line.length > 0) {
const firstChar = line.charAt(0);
if (firstChar === '[' || firstChar === ';') {
content.push(line);
} else {
const sections: string[] = line.split('=');
const key = sections[0];
let translated = line;
if (key) {
const translatedMessage = messages[key];
if (translatedMessage) {
translated = `${key}=${translatedMessage}`;
}
}
content.push(translated);
}
}
});
const basename = path.basename(name);
const filePath = `${basename}.${language.id}.isl`;
const encoded = iconv.encode(Buffer.from(content.join('\r\n'), 'utf8').toString(), innoSetup.codePage);
return new File({
path: filePath,
contents: Buffer.from(encoded),
});
}
function encodeEntities(value: string): string {
const result: string[] = [];
for (let i = 0; i < value.length; i++) {
const ch = value[i];
switch (ch) {
case '<':
result.push('<');
break;
case '>':
result.push('>');
break;
case '&':
result.push('&');
break;
default:
result.push(ch);
}
}
return result.join('');
}
function decodeEntities(value: string): string {
return value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
}
================================================
FILE: build/lib/inlineMeta.js
================================================
"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;
const event_stream_1 = __importDefault(require("event-stream"));
const path_1 = require("path");
const packageJsonMarkerId = 'BUILD_INSERT_PACKAGE_CONFIGURATION';
// TODO in order to inline `product.json`, more work is
// needed to ensure that we cover all cases where modifications
// are done to the product configuration during build. There are
// at least 2 more changes that kick in very late:
// - a `darwinUniversalAssetId` is added in`create-universal-app.ts`
// - a `target` is added in `gulpfile.vscode.win32.js`
// const productJsonMarkerId = 'BUILD_INSERT_PRODUCT_CONFIGURATION';
function inlineMeta(result, ctx) {
return result.pipe(event_stream_1.default.through(function (file) {
if (matchesFile(file, ctx)) {
let content = file.contents.toString();
let markerFound = false;
const packageMarker = `${packageJsonMarkerId}:"${packageJsonMarkerId}"`; // this needs to be the format after esbuild has processed the file (e.g. double quotes)
if (content.includes(packageMarker)) {
content = content.replace(packageMarker, JSON.stringify(JSON.parse(ctx.packageJsonFn())).slice(1, -1) /* trim braces */);
markerFound = true;
}
// const productMarker = `${productJsonMarkerId}:"${productJsonMarkerId}"`; // this needs to be the format after esbuild has processed the file (e.g. double quotes)
// if (content.includes(productMarker)) {
// content = content.replace(productMarker, JSON.stringify(JSON.parse(ctx.productJsonFn())).slice(1, -1) /* trim braces */);
// markerFound = true;
// }
if (markerFound) {
file.contents = Buffer.from(content);
}
}
this.emit('data', file);
}));
}
function matchesFile(file, ctx) {
for (const targetPath of ctx.targetPaths) {
if (file.basename === (0, path_1.basename)(targetPath)) { // TODO would be nicer to figure out root relative path to not match on false positives
return true;
}
}
return false;
}
//# sourceMappingURL=inlineMeta.js.map
================================================
FILE: build/lib/inlineMeta.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import es from 'event-stream';
import { basename } from 'path';
import File from 'vinyl';
export interface IInlineMetaContext {
readonly targetPaths: string[];
readonly packageJsonFn: () => string;
readonly productJsonFn: () => string;
}
const packageJsonMarkerId = 'BUILD_INSERT_PACKAGE_CONFIGURATION';
// TODO in order to inline `product.json`, more work is
// needed to ensure that we cover all cases where modifications
// are done to the product configuration during build. There are
// at least 2 more changes that kick in very late:
// - a `darwinUniversalAssetId` is added in`create-universal-app.ts`
// - a `target` is added in `gulpfile.vscode.win32.js`
// const productJsonMarkerId = 'BUILD_INSERT_PRODUCT_CONFIGURATION';
export function inlineMeta(result: NodeJS.ReadWriteStream, ctx: IInlineMetaContext): NodeJS.ReadWriteStream {
return result.pipe(es.through(function (file: File) {
if (matchesFile(file, ctx)) {
let content = file.contents.toString();
let markerFound = false;
const packageMarker = `${packageJsonMarkerId}:"${packageJsonMarkerId}"`; // this needs to be the format after esbuild has processed the file (e.g. double quotes)
if (content.includes(packageMarker)) {
content = content.replace(packageMarker, JSON.stringify(JSON.parse(ctx.packageJsonFn())).slice(1, -1) /* trim braces */);
markerFound = true;
}
// const productMarker = `${productJsonMarkerId}:"${productJsonMarkerId}"`; // this needs to be the format after esbuild has processed the file (e.g. double quotes)
// if (content.includes(productMarker)) {
// content = content.replace(productMarker, JSON.stringify(JSON.parse(ctx.productJsonFn())).slice(1, -1) /* trim braces */);
// markerFound = true;
// }
if (markerFound) {
file.contents = Buffer.from(content);
}
}
this.emit('data', file);
}));
}
function matchesFile(file: File, ctx: IInlineMetaContext): boolean {
for (const targetPath of ctx.targetPaths) {
if (file.basename === basename(targetPath)) { // TODO would be nicer to figure out root relative path to not match on false positives
return true;
}
}
return false;
}
================================================
FILE: build/lib/layersChecker.js
================================================
"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 typescript_1 = __importDefault(require("typescript"));
const fs_1 = require("fs");
const path_1 = require("path");
const minimatch_1 = require("minimatch");
//
// #############################################################################################
//
// A custom typescript checker for the specific task of detecting the use of certain types in a
// layer that does not allow such use. For example:
// - using DOM globals in common/node/electron-main layer (e.g. HTMLElement)
// - using node.js globals in common/browser layer (e.g. process)
//
// Make changes to below RULES to lift certain files from these checks only if absolutely needed
//
// #############################################################################################
//
// Types we assume are present in all implementations of JS VMs (node.js, browsers)
// Feel free to add more core types as you see needed if present in node.js and browsers
const CORE_TYPES = [
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'console',
'Console',
'Error',
'ErrorConstructor',
'String',
'TextDecoder',
'TextEncoder',
'self',
'queueMicrotask',
'Array',
'Uint8Array',
'Uint16Array',
'Uint32Array',
'Int8Array',
'Int16Array',
'Int32Array',
'Float32Array',
'Float64Array',
'Uint8ClampedArray',
'BigUint64Array',
'BigInt64Array',
'btoa',
'atob',
'AbortController',
'AbortSignal',
'MessageChannel',
'MessagePort',
'URL',
'URLSearchParams',
'ReadonlyArray',
'Event',
'EventTarget',
'BroadcastChannel',
'performance',
'Blob',
'crypto',
'File',
'fetch',
'RequestInit',
'Headers',
'Request',
'Response',
'Body',
'__type',
'__global',
'Performance',
'PerformanceMark',
'PerformanceObserver',
'ImportMeta',
'structuredClone',
// webcrypto has been available since Node.js 19, but still live in dom.d.ts
'Crypto',
'SubtleCrypto',
'JsonWebKey',
'MessageEvent',
];
// Types that are defined in a common layer but are known to be only
// available in native environments should not be allowed in browser
const NATIVE_TYPES = [
'NativeParsedArgs',
'INativeEnvironmentService',
'AbstractNativeEnvironmentService',
'INativeWindowConfiguration',
'ICommonNativeHostService',
'INativeHostService',
'IMainProcessService'
];
const RULES = [
// Tests: skip
{
target: '**/vs/**/test/**',
skip: true // -> skip all test files
},
// Common: vs/base/common/platform.ts
{
target: '**/vs/base/common/platform.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to postMessage() and friends
'MessageEvent',
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/base/common/async.ts
{
target: '**/vs/base/common/async.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to requestIdleCallback & cancelIdleCallback
'requestIdleCallback',
'cancelIdleCallback'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/base/common/performance.ts
{
target: '**/vs/base/common/performance.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to Performance
'Performance',
'PerformanceEntry',
'PerformanceTiming'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/environment/common/*
{
target: '**/vs/platform/environment/common/*.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [ /* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/window/common/window.ts
{
target: '**/vs/platform/window/common/window.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [ /* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/native/common/native.ts
{
target: '**/vs/platform/native/common/native.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [ /* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/native/common/nativeHostService.ts
{
target: '**/vs/platform/native/common/nativeHostService.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [ /* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/workbench/api/common/extHostExtensionService.ts
{
target: '**/vs/workbench/api/common/extHostExtensionService.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to global
'global'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/base/parts/sandbox/electron-sandbox/preload.ts
{
target: '**/vs/base/parts/sandbox/electron-sandbox/preload.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to a very small subset of node.js
'process',
'NodeJS'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Common
{
target: '**/vs/**/common/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Browser
{
target: '**/vs/**/browser/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
allowedDefinitions: [
'@types/node/stream/consumers.d.ts' // node.js started to duplicate types from lib.dom.d.ts so we have to account for that
],
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Browser (editor contrib)
{
target: '**/src/vs/editor/contrib/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// node.js
{
target: '**/vs/**/node/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
},
// Electron (sandbox)
{
target: '**/vs/**/electron-sandbox/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Electron (utility)
{
target: '**/vs/**/electron-utility/**',
allowedTypes: [
...CORE_TYPES,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event',
'Request'
],
disallowedTypes: [
'ipcMain' // not allowed, use validatedIpcMain instead
],
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
},
// Electron (main)
{
target: '**/vs/**/electron-main/**',
allowedTypes: [
...CORE_TYPES,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event',
'Request'
],
disallowedTypes: [
'ipcMain' // not allowed, use validatedIpcMain instead
],
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
}
];
const TS_CONFIG_PATH = (0, path_1.join)(__dirname, '../../', 'src', 'tsconfig.json');
let hasErrors = false;
function checkFile(program, sourceFile, rule) {
checkNode(sourceFile);
function checkNode(node) {
if (node.kind !== typescript_1.default.SyntaxKind.Identifier) {
return typescript_1.default.forEachChild(node, checkNode); // recurse down
}
const checker = program.getTypeChecker();
const symbol = checker.getSymbolAtLocation(node);
if (!symbol) {
return;
}
let _parentSymbol = symbol;
while (_parentSymbol.parent) {
_parentSymbol = _parentSymbol.parent;
}
const parentSymbol = _parentSymbol;
const text = parentSymbol.getName();
if (rule.allowedTypes?.some(allowed => allowed === text)) {
return; // override
}
if (rule.disallowedTypes?.some(disallowed => disallowed === text)) {
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
console.log(`[build/lib/layersChecker.ts]: Reference to type '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1}). Learn more about our source code organization at https://github.com/microsoft/vscode/wiki/Source-Code-Organization.`);
hasErrors = true;
return;
}
const declarations = symbol.declarations;
if (Array.isArray(declarations)) {
DeclarationLoop: for (const declaration of declarations) {
if (declaration) {
const parent = declaration.parent;
if (parent) {
const parentSourceFile = parent.getSourceFile();
if (parentSourceFile) {
const definitionFileName = parentSourceFile.fileName;
if (rule.allowedDefinitions) {
for (const allowedDefinition of rule.allowedDefinitions) {
if (definitionFileName.indexOf(allowedDefinition) >= 0) {
continue DeclarationLoop;
}
}
}
if (rule.disallowedDefinitions) {
for (const disallowedDefinition of rule.disallowedDefinitions) {
if (definitionFileName.indexOf(disallowedDefinition) >= 0) {
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
console.log(`[build/lib/layersChecker.ts]: Reference to symbol '${text}' from '${disallowedDefinition}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1}) Learn more about our source code organization at https://github.com/microsoft/vscode/wiki/Source-Code-Organization.`);
hasErrors = true;
return;
}
}
}
}
}
}
}
}
}
}
function createProgram(tsconfigPath) {
const tsConfig = typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile);
const configHostParser = { fileExists: fs_1.existsSync, readDirectory: typescript_1.default.sys.readDirectory, readFile: file => (0, fs_1.readFileSync)(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' };
const tsConfigParsed = typescript_1.default.parseJsonConfigFileContent(tsConfig.config, configHostParser, (0, path_1.resolve)((0, path_1.dirname)(tsconfigPath)), { noEmit: true });
const compilerHost = typescript_1.default.createCompilerHost(tsConfigParsed.options, true);
return typescript_1.default.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost);
}
//
// Create program and start checking
//
const program = createProgram(TS_CONFIG_PATH);
for (const sourceFile of program.getSourceFiles()) {
for (const rule of RULES) {
if ((0, minimatch_1.match)([sourceFile.fileName], rule.target).length > 0) {
if (!rule.skip) {
checkFile(program, sourceFile, rule);
}
break;
}
}
}
if (hasErrors) {
process.exit(1);
}
//# sourceMappingURL=layersChecker.js.map
================================================
FILE: build/lib/layersChecker.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import ts from 'typescript';
import { readFileSync, existsSync } from 'fs';
import { resolve, dirname, join } from 'path';
import { match } from 'minimatch';
//
// #############################################################################################
//
// A custom typescript checker for the specific task of detecting the use of certain types in a
// layer that does not allow such use. For example:
// - using DOM globals in common/node/electron-main layer (e.g. HTMLElement)
// - using node.js globals in common/browser layer (e.g. process)
//
// Make changes to below RULES to lift certain files from these checks only if absolutely needed
//
// #############################################################################################
//
// Types we assume are present in all implementations of JS VMs (node.js, browsers)
// Feel free to add more core types as you see needed if present in node.js and browsers
const CORE_TYPES = [
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'console',
'Console',
'Error',
'ErrorConstructor',
'String',
'TextDecoder',
'TextEncoder',
'self',
'queueMicrotask',
'Array',
'Uint8Array',
'Uint16Array',
'Uint32Array',
'Int8Array',
'Int16Array',
'Int32Array',
'Float32Array',
'Float64Array',
'Uint8ClampedArray',
'BigUint64Array',
'BigInt64Array',
'btoa',
'atob',
'AbortController',
'AbortSignal',
'MessageChannel',
'MessagePort',
'URL',
'URLSearchParams',
'ReadonlyArray',
'Event',
'EventTarget',
'BroadcastChannel',
'performance',
'Blob',
'crypto',
'File',
'fetch',
'RequestInit',
'Headers',
'Request',
'Response',
'Body',
'__type',
'__global',
'Performance',
'PerformanceMark',
'PerformanceObserver',
'ImportMeta',
'structuredClone',
// webcrypto has been available since Node.js 19, but still live in dom.d.ts
'Crypto',
'SubtleCrypto',
'JsonWebKey',
'MessageEvent',
];
// Types that are defined in a common layer but are known to be only
// available in native environments should not be allowed in browser
const NATIVE_TYPES = [
'NativeParsedArgs',
'INativeEnvironmentService',
'AbstractNativeEnvironmentService',
'INativeWindowConfiguration',
'ICommonNativeHostService',
'INativeHostService',
'IMainProcessService'
];
const RULES: IRule[] = [
// Tests: skip
{
target: '**/vs/**/test/**',
skip: true // -> skip all test files
},
// Common: vs/base/common/platform.ts
{
target: '**/vs/base/common/platform.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to postMessage() and friends
'MessageEvent',
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/base/common/async.ts
{
target: '**/vs/base/common/async.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to requestIdleCallback & cancelIdleCallback
'requestIdleCallback',
'cancelIdleCallback'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/base/common/performance.ts
{
target: '**/vs/base/common/performance.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to Performance
'Performance',
'PerformanceEntry',
'PerformanceTiming'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/environment/common/*
{
target: '**/vs/platform/environment/common/*.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [/* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/window/common/window.ts
{
target: '**/vs/platform/window/common/window.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [/* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/native/common/native.ts
{
target: '**/vs/platform/native/common/native.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [/* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/platform/native/common/nativeHostService.ts
{
target: '**/vs/platform/native/common/nativeHostService.ts',
allowedTypes: CORE_TYPES,
disallowedTypes: [/* Ignore native types that are defined from here */],
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/workbench/api/common/extHostExtensionService.ts
{
target: '**/vs/workbench/api/common/extHostExtensionService.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to global
'global'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Common: vs/base/parts/sandbox/electron-sandbox/preload.ts
{
target: '**/vs/base/parts/sandbox/electron-sandbox/preload.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to a very small subset of node.js
'process',
'NodeJS'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Common
{
target: '**/vs/**/common/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts', // no DOM
'@types/node' // no node.js
]
},
// Browser
{
target: '**/vs/**/browser/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
allowedDefinitions: [
'@types/node/stream/consumers.d.ts' // node.js started to duplicate types from lib.dom.d.ts so we have to account for that
],
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Browser (editor contrib)
{
target: '**/src/vs/editor/contrib/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// node.js
{
target: '**/vs/**/node/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
},
// Electron (sandbox)
{
target: '**/vs/**/electron-sandbox/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Electron (utility)
{
target: '**/vs/**/electron-utility/**',
allowedTypes: [
...CORE_TYPES,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event',
'Request'
],
disallowedTypes: [
'ipcMain' // not allowed, use validatedIpcMain instead
],
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
},
// Electron (main)
{
target: '**/vs/**/electron-main/**',
allowedTypes: [
...CORE_TYPES,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event',
'Request'
],
disallowedTypes: [
'ipcMain' // not allowed, use validatedIpcMain instead
],
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
}
];
const TS_CONFIG_PATH = join(__dirname, '../../', 'src', 'tsconfig.json');
interface IRule {
target: string;
skip?: boolean;
allowedTypes?: string[];
allowedDefinitions?: string[];
disallowedDefinitions?: string[];
disallowedTypes?: string[];
}
let hasErrors = false;
function checkFile(program: ts.Program, sourceFile: ts.SourceFile, rule: IRule) {
checkNode(sourceFile);
function checkNode(node: ts.Node): void {
if (node.kind !== ts.SyntaxKind.Identifier) {
return ts.forEachChild(node, checkNode); // recurse down
}
const checker = program.getTypeChecker();
const symbol = checker.getSymbolAtLocation(node);
if (!symbol) {
return;
}
let _parentSymbol: any = symbol;
while (_parentSymbol.parent) {
_parentSymbol = _parentSymbol.parent;
}
const parentSymbol = _parentSymbol as ts.Symbol;
const text = parentSymbol.getName();
if (rule.allowedTypes?.some(allowed => allowed === text)) {
return; // override
}
if (rule.disallowedTypes?.some(disallowed => disallowed === text)) {
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
console.log(`[build/lib/layersChecker.ts]: Reference to type '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1}). Learn more about our source code organization at https://github.com/microsoft/vscode/wiki/Source-Code-Organization.`);
hasErrors = true;
return;
}
const declarations = symbol.declarations;
if (Array.isArray(declarations)) {
DeclarationLoop: for (const declaration of declarations) {
if (declaration) {
const parent = declaration.parent;
if (parent) {
const parentSourceFile = parent.getSourceFile();
if (parentSourceFile) {
const definitionFileName = parentSourceFile.fileName;
if (rule.allowedDefinitions) {
for (const allowedDefinition of rule.allowedDefinitions) {
if (definitionFileName.indexOf(allowedDefinition) >= 0) {
continue DeclarationLoop;
}
}
}
if (rule.disallowedDefinitions) {
for (const disallowedDefinition of rule.disallowedDefinitions) {
if (definitionFileName.indexOf(disallowedDefinition) >= 0) {
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
console.log(`[build/lib/layersChecker.ts]: Reference to symbol '${text}' from '${disallowedDefinition}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1}) Learn more about our source code organization at https://github.com/microsoft/vscode/wiki/Source-Code-Organization.`);
hasErrors = true;
return;
}
}
}
}
}
}
}
}
}
}
function createProgram(tsconfigPath: string): ts.Program {
const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
const configHostParser: ts.ParseConfigHost = { fileExists: existsSync, readDirectory: ts.sys.readDirectory, readFile: file => readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' };
const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, resolve(dirname(tsconfigPath)), { noEmit: true });
const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true);
return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost);
}
//
// Create program and start checking
//
const program = createProgram(TS_CONFIG_PATH);
for (const sourceFile of program.getSourceFiles()) {
for (const rule of RULES) {
if (match([sourceFile.fileName], rule.target).length > 0) {
if (!rule.skip) {
checkFile(program, sourceFile, rule);
}
break;
}
}
}
if (hasErrors) {
process.exit(1);
}
================================================
FILE: build/lib/mangle/index.js
================================================
"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;
const node_v8_1 = __importDefault(require("node:v8"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const process_1 = require("process");
const source_map_1 = require("source-map");
const typescript_1 = __importDefault(require("typescript"));
const url_1 = require("url");
const workerpool_1 = __importDefault(require("workerpool"));
const staticLanguageServiceHost_1 = require("./staticLanguageServiceHost");
const buildfile = require('../../buildfile');
class ShortIdent {
prefix;
static _keywords = new Set(['await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
'default', 'delete', 'do', 'else', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if',
'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw',
'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']);
static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$_'.split('');
_value = 0;
constructor(prefix) {
this.prefix = prefix;
}
next(isNameTaken) {
const candidate = this.prefix + ShortIdent.convert(this._value);
this._value++;
if (ShortIdent._keywords.has(candidate) || /^[_0-9]/.test(candidate) || isNameTaken?.(candidate)) {
// try again
return this.next(isNameTaken);
}
return candidate;
}
static convert(n) {
const base = this._alphabet.length;
let result = '';
do {
const rest = n % base;
result += this._alphabet[rest];
n = (n / base) | 0;
} while (n > 0);
return result;
}
}
var FieldType;
(function (FieldType) {
FieldType[FieldType["Public"] = 0] = "Public";
FieldType[FieldType["Protected"] = 1] = "Protected";
FieldType[FieldType["Private"] = 2] = "Private";
})(FieldType || (FieldType = {}));
class ClassData {
fileName;
node;
fields = new Map();
replacements;
parent;
children;
constructor(fileName, 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)) {
// method `foo() {}`
candidates.push(member);
}
else if (typescript_1.default.isPropertyDeclaration(member)) {
// property `foo = 234`
candidates.push(member);
}
else if (typescript_1.default.isGetAccessor(member)) {
// getter: `get foo() { ... }`
candidates.push(member);
}
else if (typescript_1.default.isSetAccessor(member)) {
// setter: `set foo() { ... }`
candidates.push(member);
}
else if (typescript_1.default.isConstructorDeclaration(member)) {
// constructor-prop:`constructor(private foo) {}`
for (const param of member.parameters) {
if (hasModifier(param, typescript_1.default.SyntaxKind.PrivateKeyword)
|| hasModifier(param, typescript_1.default.SyntaxKind.ProtectedKeyword)
|| hasModifier(param, typescript_1.default.SyntaxKind.PublicKeyword)
|| hasModifier(param, typescript_1.default.SyntaxKind.ReadonlyKeyword)) {
candidates.push(param);
}
}
}
}
for (const member of candidates) {
const ident = ClassData._getMemberName(member);
if (!ident) {
continue;
}
const type = ClassData._getFieldType(member);
this.fields.set(ident, { type, pos: member.name.getStart() });
}
}
static _getMemberName(node) {
if (!node.name) {
return undefined;
}
const { name } = node;
let ident = name.getText();
if (name.kind === typescript_1.default.SyntaxKind.ComputedPropertyName) {
if (name.expression.kind !== typescript_1.default.SyntaxKind.StringLiteral) {
// unsupported: [Symbol.foo] or [abc + 'field']
return;
}
// ['foo']
ident = name.expression.getText().slice(1, -1);
}
return ident;
}
static _getFieldType(node) {
if (hasModifier(node, typescript_1.default.SyntaxKind.PrivateKeyword)) {
return 2 /* FieldType.Private */;
}
else if (hasModifier(node, typescript_1.default.SyntaxKind.ProtectedKeyword)) {
return 1 /* FieldType.Protected */;
}
else {
return 0 /* FieldType.Public */;
}
}
static _shouldMangle(type) {
return type === 2 /* FieldType.Private */
|| type === 1 /* FieldType.Protected */;
}
static makeImplicitPublicActuallyPublic(data, reportViolation) {
// TS-HACK
// A subtype can make an inherited protected field public. To prevent accidential
// mangling of public fields we mark the original (protected) fields as public...
for (const [name, info] of data.fields) {
if (info.type !== 0 /* FieldType.Public */) {
continue;
}
let parent = data.parent;
while (parent) {
if (parent.fields.get(name)?.type === 1 /* FieldType.Protected */) {
const parentPos = parent.node.getSourceFile().getLineAndCharacterOfPosition(parent.fields.get(name).pos);
const infoPos = data.node.getSourceFile().getLineAndCharacterOfPosition(info.pos);
reportViolation(name, `'${name}' from ${parent.fileName}:${parentPos.line + 1}`, `${data.fileName}:${infoPos.line + 1}`);
parent.fields.get(name).type = 0 /* FieldType.Public */;
}
parent = parent.parent;
}
}
}
static fillInReplacement(data) {
if (data.replacements) {
// already done
return;
}
// fill in parents first
if (data.parent) {
ClassData.fillInReplacement(data.parent);
}
data.replacements = new Map();
const isNameTaken = (name) => {
// locally taken
if (data._isNameTaken(name)) {
return true;
}
// parents
let parent = data.parent;
while (parent) {
if (parent._isNameTaken(name)) {
return true;
}
parent = parent.parent;
}
// children
if (data.children) {
const stack = [...data.children];
while (stack.length) {
const node = stack.pop();
if (node._isNameTaken(name)) {
return true;
}
if (node.children) {
stack.push(...node.children);
}
}
}
return false;
};
const identPool = new ShortIdent('');
for (const [name, info] of data.fields) {
if (ClassData._shouldMangle(info.type)) {
const shortName = identPool.next(isNameTaken);
data.replacements.set(name, shortName);
}
}
}
// a name is taken when a field that doesn't get mangled exists or
// when the name is already in use for replacement
_isNameTaken(name) {
if (this.fields.has(name) && !ClassData._shouldMangle(this.fields.get(name).type)) {
// public field
return true;
}
if (this.replacements) {
for (const shortName of this.replacements.values()) {
if (shortName === name) {
// replaced already (happens wih super types)
return true;
}
}
}
if (isNameTakenInFile(this.node, name)) {
return true;
}
return false;
}
lookupShortName(name) {
let value = this.replacements.get(name);
let parent = this.parent;
while (parent) {
if (parent.replacements.has(name) && parent.fields.get(name)?.type === 1 /* FieldType.Protected */) {
value = parent.replacements.get(name) ?? value;
}
parent = parent.parent;
}
return value;
}
// --- parent chaining
addChild(child) {
this.children ??= [];
this.children.push(child);
child.parent = this;
}
}
function isNameTakenInFile(node, name) {
const identifiers = node.getSourceFile().identifiers;
if (identifiers instanceof Map) {
if (identifiers.has(name)) {
return true;
}
}
return false;
}
const skippedExportMangledFiles = [
// Build
'css.build',
// Monaco
'editorCommon',
'editorOptions',
'editorZoom',
'standaloneEditor',
'standaloneEnums',
'standaloneLanguages',
// Generated
'extensionsApiProposals',
// Module passed around as type
'pfs',
// entry points
...[
buildfile.workerEditor,
buildfile.workerExtensionHost,
buildfile.workerNotebook,
buildfile.workerLanguageDetection,
buildfile.workerLocalFileSearch,
buildfile.workerProfileAnalysis,
buildfile.workerOutputLinks,
buildfile.workerBackgroundTokenization,
buildfile.workbenchDesktop,
buildfile.workbenchWeb,
buildfile.code,
buildfile.codeWeb
].flat().map(x => x.name),
];
const skippedExportMangledProjects = [
// Test projects
'vscode-api-tests',
// These projects use webpack to dynamically rewrite imports, which messes up our mangling
'configuration-editing',
'microsoft-authentication',
'github-authentication',
'html-language-features/server',
];
const skippedExportMangledSymbols = [
// Don't mangle extension entry points
'activate',
'deactivate',
];
class DeclarationData {
fileName;
node;
replacementName;
constructor(fileName, node, fileIdents) {
this.fileName = fileName;
this.node = node;
// Todo: generate replacement names based on usage count, with more used names getting shorter identifiers
this.replacementName = fileIdents.next();
}
getLocations(service) {
if (typescript_1.default.isVariableDeclaration(this.node)) {
// If the const aliases any types, we need to rename those too
const definitionResult = service.getDefinitionAndBoundSpan(this.fileName, this.node.name.getStart());
if (definitionResult?.definitions && definitionResult.definitions.length > 1) {
return definitionResult.definitions.map(x => ({ fileName: x.fileName, offset: x.textSpan.start }));
}
}
return [{
fileName: this.fileName,
offset: this.node.name.getStart()
}];
}
shouldMangle(newName) {
const currentName = this.node.name.getText();
if (currentName.startsWith('$') || skippedExportMangledSymbols.includes(currentName)) {
return false;
}
// New name is longer the existing one :'(
if (newName.length >= currentName.length) {
return false;
}
// Don't mangle functions we've explicitly opted out
if (this.node.getFullText().includes('@skipMangle')) {
return false;
}
return true;
}
}
/**
* TypeScript2TypeScript transformer that mangles all private and protected fields
*
* 1. Collect all class fields (properties, methods)
* 2. Collect all sub and super-type relations between classes
* 3. Compute replacement names for each field
* 4. Lookup rename locations for these fields
* 5. Prepare and apply edits
*/
class Mangler {
projectPath;
log;
config;
allClassDataByKey = new Map();
allExportedSymbols = new Set();
renameWorkerPool;
constructor(projectPath, log = () => { }, config) {
this.projectPath = projectPath;
this.log = log;
this.config = config;
this.renameWorkerPool = workerpool_1.default.pool(path_1.default.join(__dirname, 'renameWorker.js'), {
maxWorkers: 4,
minWorkers: 'max'
});
}
async computeNewFileContents(strictImplicitPublicHandling) {
const service = typescript_1.default.createLanguageService(new staticLanguageServiceHost_1.StaticLanguageServiceHost(this.projectPath));
// STEP:
// - Find all classes and their field info.
// - Find exported symbols.
const fileIdents = new ShortIdent('$');
const visit = (node) => {
if (this.config.manglePrivateFields) {
if (typescript_1.default.isClassDeclaration(node) || typescript_1.default.isClassExpression(node)) {
const anchor = node.name ?? node;
const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`;
if (this.allClassDataByKey.has(key)) {
throw new Error('DUPE?');
}
this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node));
}
}
if (this.config.mangleExports) {
// Find exported classes, functions, and vars
if ((
// Exported class
typescript_1.default.isClassDeclaration(node)
&& hasModifier(node, typescript_1.default.SyntaxKind.ExportKeyword)
&& node.name) || (
// Exported function
typescript_1.default.isFunctionDeclaration(node)
&& typescript_1.default.isSourceFile(node.parent)
&& hasModifier(node, typescript_1.default.SyntaxKind.ExportKeyword)
&& node.name && node.body // On named function and not on the overload
) || (
// Exported variable
typescript_1.default.isVariableDeclaration(node)
&& hasModifier(node.parent.parent, typescript_1.default.SyntaxKind.ExportKeyword) // Variable statement is exported
&& typescript_1.default.isSourceFile(node.parent.parent.parent))
// Disabled for now because we need to figure out how to handle
// enums that are used in monaco or extHost interfaces.
/* || (
// Exported enum
ts.isEnumDeclaration(node)
&& ts.isSourceFile(node.parent)
&& hasModifier(node, ts.SyntaxKind.ExportKeyword)
&& !hasModifier(node, ts.SyntaxKind.ConstKeyword) // Don't bother mangling const enums because these are inlined
&& node.name
*/
) {
if (isInAmbientContext(node)) {
return;
}
this.allExportedSymbols.add(new DeclarationData(node.getSourceFile().fileName, node, fileIdents));
}
}
typescript_1.default.forEachChild(node, visit);
};
for (const file of service.getProgram().getSourceFiles()) {
if (!file.isDeclarationFile) {
typescript_1.default.forEachChild(file, visit);
}
}
this.log(`Done collecting. Classes: ${this.allClassDataByKey.size}. Exported symbols: ${this.allExportedSymbols.size}`);
// STEP: connect sub and super-types
const setupParents = (data) => {
const extendsClause = data.node.heritageClauses?.find(h => h.token === typescript_1.default.SyntaxKind.ExtendsKeyword);
if (!extendsClause) {
// no EXTENDS-clause
return;
}
const info = service.getDefinitionAtPosition(data.fileName, extendsClause.types[0].expression.getEnd());
if (!info || info.length === 0) {
// throw new Error('SUPER type not found');
return;
}
if (info.length !== 1) {
// inherits from declared/library type
return;
}
const [definition] = info;
const key = `${definition.fileName}|${definition.textSpan.start}`;
const parent = this.allClassDataByKey.get(key);
if (!parent) {
// throw new Error(`SUPER type not found: ${key}`);
return;
}
parent.addChild(data);
};
for (const data of this.allClassDataByKey.values()) {
setupParents(data);
}
// STEP: make implicit public (actually protected) field really public
const violations = new Map();
let violationsCauseFailure = false;
for (const data of this.allClassDataByKey.values()) {
ClassData.makeImplicitPublicActuallyPublic(data, (name, what, why) => {
const arr = violations.get(what);
if (arr) {
arr.push(why);
}
else {
violations.set(what, [why]);
}
if (strictImplicitPublicHandling && !strictImplicitPublicHandling.has(name)) {
violationsCauseFailure = true;
}
});
}
for (const [why, whys] of violations) {
this.log(`WARN: ${why} became PUBLIC because of: ${whys.join(' , ')}`);
}
if (violationsCauseFailure) {
const message = 'Protected fields have been made PUBLIC. This hurts minification and is therefore not allowed. Review the WARN messages further above';
this.log(`ERROR: ${message}`);
throw new Error(message);
}
// STEP: compute replacement names for each class
for (const data of this.allClassDataByKey.values()) {
ClassData.fillInReplacement(data);
}
this.log(`Done creating class replacements`);
// STEP: prepare rename edits
this.log(`Starting prepare rename edits`);
const editsByFile = new Map();
const appendEdit = (fileName, edit) => {
const edits = editsByFile.get(fileName);
if (!edits) {
editsByFile.set(fileName, [edit]);
}
else {
edits.push(edit);
}
};
const appendRename = (newText, loc) => {
appendEdit(loc.fileName, {
newText: (loc.prefixText || '') + newText + (loc.suffixText || ''),
offset: loc.textSpan.start,
length: loc.textSpan.length
});
};
const renameResults = [];
const queueRename = (fileName, pos, newName) => {
renameResults.push(Promise.resolve(this.renameWorkerPool.exec('findRenameLocations', [this.projectPath, fileName, pos]))
.then((locations) => ({ newName, locations })));
};
for (const data of this.allClassDataByKey.values()) {
if (hasModifier(data.node, typescript_1.default.SyntaxKind.DeclareKeyword)) {
continue;
}
fields: for (const [name, info] of data.fields) {
if (!ClassData._shouldMangle(info.type)) {
continue fields;
}
// TS-HACK: protected became public via 'some' child
// and because of that we might need to ignore this now
let parent = data.parent;
while (parent) {
if (parent.fields.get(name)?.type === 0 /* FieldType.Public */) {
continue fields;
}
parent = parent.parent;
}
const newName = data.lookupShortName(name);
queueRename(data.fileName, info.pos, newName);
}
}
for (const data of this.allExportedSymbols.values()) {
if (data.fileName.endsWith('.d.ts')
|| skippedExportMangledProjects.some(proj => data.fileName.includes(proj))
|| skippedExportMangledFiles.some(file => data.fileName.endsWith(file + '.ts'))) {
continue;
}
if (!data.shouldMangle(data.replacementName)) {
continue;
}
const newText = data.replacementName;
for (const { fileName, offset } of data.getLocations(service)) {
queueRename(fileName, offset, newText);
}
}
await Promise.all(renameResults).then((result) => {
for (const { newName, locations } of result) {
for (const loc of locations) {
appendRename(newName, loc);
}
}
});
await this.renameWorkerPool.terminate();
this.log(`Done preparing edits: ${editsByFile.size} files`);
// STEP: apply all rename edits (per file)
const result = new Map();
let savedBytes = 0;
for (const item of service.getProgram().getSourceFiles()) {
const { mapRoot, sourceRoot } = service.getProgram().getCompilerOptions();
const projectDir = path_1.default.dirname(this.projectPath);
const sourceMapRoot = mapRoot ?? (0, url_1.pathToFileURL)(sourceRoot ?? projectDir).toString();
// source maps
let generator;
let newFullText;
const edits = editsByFile.get(item.fileName);
if (!edits) {
// just copy
newFullText = item.getFullText();
}
else {
// source map generator
const relativeFileName = normalize(path_1.default.relative(projectDir, item.fileName));
const mappingsByLine = new Map();
// apply renames
edits.sort((a, b) => b.offset - a.offset);
const characters = item.getFullText().split('');
let lastEdit;
for (const edit of edits) {
if (lastEdit && lastEdit.offset === edit.offset) {
//
if (lastEdit.length !== edit.length || lastEdit.newText !== edit.newText) {
this.log('ERROR: Overlapping edit', item.fileName, edit.offset, edits);
throw new Error('OVERLAPPING edit');
}
else {
continue;
}
}
lastEdit = edit;
const mangledName = characters.splice(edit.offset, edit.length, edit.newText).join('');
savedBytes += mangledName.length - edit.newText.length;
// source maps
const pos = item.getLineAndCharacterOfPosition(edit.offset);
let mappings = mappingsByLine.get(pos.line);
if (!mappings) {
mappings = [];
mappingsByLine.set(pos.line, mappings);
}
mappings.unshift({
source: relativeFileName,
original: { line: pos.line + 1, column: pos.character },
generated: { line: pos.line + 1, column: pos.character },
name: mangledName
}, {
source: relativeFileName,
original: { line: pos.line + 1, column: pos.character + edit.length },
generated: { line: pos.line + 1, column: pos.character + edit.newText.length },
});
}
// source map generation, make sure to get mappings per line correct
generator = new source_map_1.SourceMapGenerator({ file: path_1.default.basename(item.fileName), sourceRoot: sourceMapRoot });
generator.setSourceContent(relativeFileName, item.getFullText());
for (const [, mappings] of mappingsByLine) {
let lineDelta = 0;
for (const mapping of mappings) {
generator.addMapping({
...mapping,
generated: { line: mapping.generated.line, column: mapping.generated.column - lineDelta }
});
lineDelta += mapping.original.column - mapping.generated.column;
}
}
newFullText = characters.join('');
}
result.set(item.fileName, { out: newFullText, sourceMap: generator?.toString() });
}
service.dispose();
this.renameWorkerPool.terminate();
this.log(`Done: ${savedBytes / 1000}kb saved, memory-usage: ${JSON.stringify(node_v8_1.default.getHeapStatistics())}`);
return result;
}
}
exports.Mangler = Mangler;
// --- ast utils
function hasModifier(node, kind) {
const modifiers = typescript_1.default.canHaveModifiers(node) ? typescript_1.default.getModifiers(node) : undefined;
return Boolean(modifiers?.find(mode => mode.kind === kind));
}
function isInAmbientContext(node) {
for (let p = node.parent; p; p = p.parent) {
if (typescript_1.default.isModuleDeclaration(p)) {
return true;
}
}
return false;
}
function normalize(path) {
return path.replace(/\\/g, '/');
}
async function _run() {
const root = path_1.default.join(__dirname, '..', '..', '..');
const projectBase = path_1.default.join(root, 'src');
const projectPath = path_1.default.join(projectBase, 'tsconfig.json');
const newProjectBase = path_1.default.join(path_1.default.dirname(projectBase), path_1.default.basename(projectBase) + '2');
fs_1.default.cpSync(projectBase, newProjectBase, { recursive: true });
const mangler = new Mangler(projectPath, console.log, {
mangleExports: true,
manglePrivateFields: true,
});
for (const [fileName, contents] of await mangler.computeNewFileContents(new Set(['saveState']))) {
const newFilePath = path_1.default.join(newProjectBase, path_1.default.relative(projectBase, fileName));
await fs_1.default.promises.mkdir(path_1.default.dirname(newFilePath), { recursive: true });
await fs_1.default.promises.writeFile(newFilePath, contents.out);
if (contents.sourceMap) {
await fs_1.default.promises.writeFile(newFilePath + '.map', contents.sourceMap);
}
}
}
if (__filename === process_1.argv[1]) {
_run();
}
//# sourceMappingURL=index.js.map
================================================
FILE: build/lib/mangle/index.ts
================================================
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import v8 from 'node:v8';
import fs from 'fs';
import path from 'path';
import { argv } from 'process';
import { Mapping, SourceMapGenerator } from 'source-map';
import ts from 'typescript';
import { pathToFileURL } from 'url';
import workerpool from 'workerpool';
import { StaticLanguageServiceHost } from './staticLanguageServiceHost';
const buildfile = require('../../buildfile');
class ShortIdent {
private static _keywords = new Set(['await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
'default', 'delete', 'do', 'else', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if',
'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw',
'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']);
private static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$_'.split('');
private _value = 0;
constructor(
private readonly prefix: string
) { }
next(isNameTaken?: (name: string) => boolean): string {
const candidate = this.prefix + ShortIdent.convert(this._value);
this._value++;
if (ShortIdent._keywords.has(candidate) || /^[_0-9]/.test(candidate) || isNameTaken?.(candidate)) {
// try again
return this.next(isNameTaken);
}
return candidate;
}
private static convert(n: number): string {
const base = this._alphabet.length;
let result = '';
do {
const rest = n % base;
result += this._alphabet[rest];
n = (n / base) | 0;
} while (n > 0);
return result;
}
}
const enum FieldType {
Public,
Protected,
Private
}
class ClassData {
fields = new Map();
private replacements: Map | undefined;
parent: ClassData | undefined;
children: ClassData[] | undefined;
constructor(
readonly fileName: string,
readonly node: ts.ClassDeclaration | ts.ClassExpression,
) {
// 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)
const candidates: (ts.NamedDeclaration)[] = [];
for (const member of node.members) {
if (ts.isMethodDeclaration(member)) {
// method `foo() {}`
candidates.push(member);
} else if (ts.isPropertyDeclaration(member)) {
// property `foo = 234`
candidates.push(member);
} else if (ts.isGetAccessor(member)) {
// getter: `get foo() { ... }`
candidates.push(member);
} else if (ts.isSetAccessor(member)) {
// setter: `set foo() { ... }`
candidates.push(member);
} else if (ts.isConstructorDeclaration(member)) {
// constructor-prop:`constructor(private foo) {}`
for (const param of member.parameters) {
if (hasModifier(param, ts.SyntaxKind.PrivateKeyword)
|| hasModifier(param, ts.SyntaxKind.ProtectedKeyword)
|| hasModifier(param, ts.SyntaxKind.PublicKeyword)
|| hasModifier(param, ts.SyntaxKind.ReadonlyKeyword)
) {
candidates.push(param);
}
}
}
}
for (const member of candidates) {
const ident = ClassData._getMemberName(member);
if (!ident) {
continue;
}
const type = ClassData._getFieldType(member);
this.fields.set(ident, { type, pos: member.name!.getStart() });
}
}
private static _getMemberName(node: ts.NamedDeclaration): string | undefined {
if (!node.name) {
return undefined;
}
const { name } = node;
let ident = name.getText();
if (name.kind === ts.SyntaxKind.ComputedPropertyName) {
if (name.expression.kind !== ts.SyntaxKind.StringLiteral) {
// unsupported: [Symbol.foo] or [abc + 'field']
return;
}
// ['foo']
ident = name.expression.getText().slice(1, -1);
}
return ident;
}
private static _getFieldType(node: ts.Node): FieldType {
if (hasModifier(node, ts.SyntaxKind.PrivateKeyword)) {
return FieldType.Private;
} else if (hasModifier(node, ts.SyntaxKind.ProtectedKeyword)) {
return FieldType.Protected;
} else {
return FieldType.Public;
}
}
static _shouldMangle(type: FieldType): boolean {
return type === FieldType.Private
|| type === FieldType.Protected
;
}
static makeImplicitPublicActuallyPublic(data: ClassData, reportViolation: (name: string, what: string, why: string) => void): void {
// TS-HACK
// A subtype can make an inherited protected field public. To prevent accidential
// mangling of public fields we mark the original (protected) fields as public...
for (const [name, info] of data.fields) {
if (info.type !== FieldType.Public) {
continue;
}
let parent: ClassData | undefined = data.parent;
while (parent) {
if (parent.fields.get(name)?.type === FieldType.Protected) {
const parentPos = parent.node.getSourceFile().getLineAndCharacterOfPosition(parent.fields.get(name)!.pos);
const infoPos = data.node.getSourceFile().getLineAndCharacterOfPosition(info.pos);
reportViolation(name, `'${name}' from ${parent.fileName}:${parentPos.line + 1}`, `${data.fileName}:${infoPos.line + 1}`);
parent.fields.get(name)!.type = FieldType.Public;
}
parent = parent.parent;
}
}
}
static fillInReplacement(data: ClassData) {
if (data.replacements) {
// already done
return;
}
// fill in parents first
if (data.parent) {
ClassData.fillInReplacement(data.parent);
}
data.replacements = new Map();
const isNameTaken = (name: string) => {
// locally taken
if (data._isNameTaken(name)) {
return true;
}
// parents
let parent: ClassData | undefined = data.parent;
while (parent) {
if (parent._isNameTaken(name)) {
return true;
}
parent = parent.parent;
}
// children
if (data.children) {
const stack = [...data.children];
while (stack.length) {
const node = stack.pop()!;
if (node._isNameTaken(name)) {
return true;
}
if (node.children) {
stack.push(...node.children);
}
}
}
return false;
};
const identPool = new ShortIdent('');
for (const [name, info] of data.fields) {
if (ClassData._shouldMangle(info.type)) {
const shortName = identPool.next(isNameTaken);
data.replacements.set(name, shortName);
}
}
}
// a name is taken when a field that doesn't get mangled exists or
// when the name is already in use for replacement
private _isNameTaken(name: string) {
if (this.fields.has(name) && !ClassData._shouldMangle(this.fields.get(name)!.type)) {
// public field
return true;
}
if (this.replacements) {
for (const shortName of this.replacements.values()) {
if (shortName === name) {
// replaced already (happens wih super types)
return true;
}
}
}
if (isNameTakenInFile(this.node, name)) {
return true;
}
return false;
}
lookupShortName(name: string): string {
let value = this.replacements!.get(name)!;
let parent = this.parent;
while (parent) {
if (parent.replacements!.has(name) && parent.fields.get(name)?.type === FieldType.Protected) {
value = parent.replacements!.get(name)! ?? value;
}
parent = parent.parent;
}
return value;
}
// --- parent chaining
addChild(child: ClassData) {
this.children ??= [];
this.children.push(child);
child.parent = this;
}
}
function isNameTakenInFile(node: ts.Node, name: string): boolean {
const identifiers = (node.getSourceFile()).identifiers;
if (identifiers instanceof Map) {
if (identifiers.has(name)) {
return true;
}
}
return false;
}
const skippedExportMangledFiles = [
// Build
'css.build',
// Monaco
'editorCommon',
'editorOptions',
'editorZoom',
'standaloneEditor',
'standaloneEnums',
'standaloneLanguages',
// Generated
'extensionsApiProposals',
// Module passed around as type
'pfs',
// entry points
...[
buildfile.workerEditor,
buildfile.workerExtensionHost,
buildfile.workerNotebook,
buildfile.workerLanguageDetection,
buildfile.workerLocalFileSearch,
buildfile.workerProfileAnalysis,
buildfile.workerOutputLinks,
buildfile.workerBackgroundTokenization,
buildfile.workbenchDesktop,
buildfile.workbenchWeb,
buildfile.code,
buildfile.codeWeb
].flat().map(x => x.name),
];
const skippedExportMangledProjects = [
// Test projects
'vscode-api-tests',
// These projects use webpack to dynamically rewrite imports, which messes up our mangling
'configuration-editing',
'microsoft-authentication',
'github-authentication',
'html-language-features/server',
];
const skippedExportMangledSymbols = [
// Don't mangle extension entry points
'activate',
'deactivate',
];
class DeclarationData {
readonly replacementName: string;
constructor(
readonly fileName: string,
readonly node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.EnumDeclaration | ts.VariableDeclaration,
fileIdents: ShortIdent,
) {
// Todo: generate replacement names based on usage count, with more used names getting shorter identifiers
this.replacementName = fileIdents.next();
}
getLocations(service: ts.LanguageService): Iterable<{ fileName: string; offset: number }> {
if (ts.isVariableDeclaration(this.node)) {
// If the const aliases any types, we need to rename those too
const definitionResult = service.getDefinitionAndBoundSpan(this.fileName, this.node.name.getStart());
if (definitionResult?.definitions && definitionResult.definitions.length > 1) {
return definitionResult.definitions.map(x => ({ fileName: x.fileName, offset: x.textSpan.start }));
}
}
return [{
fileName: this.fileName,
offset: this.node.name!.getStart()
}];
}
shouldMangle(newName: string): boolean {
const currentName = this.node.name!.getText();
if (currentName.startsWith('$') || skippedExportMangledSymbols.includes(currentName)) {
return false;
}
// New name is longer the existing one :'(
if (newName.length >= currentName.length) {
return false;
}
// Don't mangle functions we've explicitly opted out
if (this.node.getFullText().includes('@skipMangle')) {
return false;
}
return true;
}
}
export interface MangleOutput {
out: string;
sourceMap?: string;
}
/**
* TypeScript2TypeScript transformer that mangles all private and protected fields
*
* 1. Collect all class fields (properties, methods)
* 2. Collect all sub and super-type relations between classes
* 3. Compute replacement names for each field
* 4. Lookup rename locations for these fields
* 5. Prepare and apply edits
*/
export class Mangler {
private readonly allClassDataByKey = new Map();
private readonly allExportedSymbols = new Set();
private readonly renameWorkerPool: workerpool.WorkerPool;
constructor(
private readonly projectPath: string,
private readonly log: typeof console.log = () => { },
private readonly config: { readonly manglePrivateFields: boolean; readonly mangleExports: boolean },
) {
this.renameWorkerPool = workerpool.pool(path.join(__dirname, 'renameWorker.js'), {
maxWorkers: 4,
minWorkers: 'max'
});
}
async computeNewFileContents(strictImplicitPublicHandling?: Set): Promise