Merge vscode source through release 1.79.2 (#23482)

* log when an editor action doesn't run because of enablement

* notebooks create/dispose editors. this means controllers must be created eagerly (😢) and that notebooks need a custom way of plugging comparision keys for session. works unless creating another session for the same cell of a duplicated editor

* Set offSide to sql lang configuration to true (#183461)

* Fixes #181764 (#183550)

* fix typo

* Always scroll down and focus the input (#183557)

* Fixes #180386 (#183561)

* cli: ensure ordering of rpc server messages (#183558)

* cli: ensure ordering of rpc server messages

Sending lots of messages to a stream would block them around the async
tokio mutex, which is "fair" so doesn't preserve ordering. Instead, use
the write_loop approach I introduced to the server_multiplexer for the
same reason some time ago.

* fix clippy

* update for May endgame

* testing: allow invalidateTestResults to take an array (#183569)

* Document `ShareProvider` API proposal (#183568)

* Document `ShareProvider` API proposal

* Remove mention of VS Code from JSDoc

* Add support for rendering svg and md in welcome message (#183580)

* Remove toggle setting more eagerly (#183584)

* rm message abt macOS

* Change text (#183589)

* Change text

* Accidentally changed the wrong file

* cli: improve output for code tunnel status (#183571)

* testing: allow invalidateTestResults to take an array

* cli: improve output for code tunnel status

Fixes #183570

* [json/css/html] update services (#183595)

* Add experimental setting to enable this dialog

* Fix exporting chat model to JSON before it is initialized (#183597)

* minimum scrolling to reveal the next cell on shift+enter (#183600)

do minimum scrolling to reveal the next cell on Execute cell and select next

* Fixing Jupyter notebook issue 13263 (#183527)

fix for the issue, still need to understand why there is strange focusing

* Tweak proposed API JSDoc (#183590)

* Tweak proposed API JSDoc

* workbench -> workspace

* fix ? operator

* Use active editor and show progress when sharing (#183603)

Use active editor and show progress

* use scroll setting variable correctly

* Schedule welcome widget to show once between typing. (#183606)

* Schedule dialog to show once between typing

* Don't re-render if already displayed once

* Add F10 keybinding for debugger step, even on Web. (#183510)

Fixes #181792.
Previously, for Web the keyboard shortcut was Alt-F10, because it was
believed that F10 could not be bound on browsers. This turned out to be
incorrect, so we make the shortcut consistent (F10) with desktop VSCode
which is also what many other debuggers use.
We keep Alt-F10 on web as a secondary keybinding to keep the experience
some web users may have gotten used to by now.

* Also pass process.env

* Restore missing chat clear commands (#183651)

* chore: update electron@22.5.4 (#183716)

* Show remote indicator in web when remoteAuthority is set (#183728)

* feat: .vuerc as json file (#153017)

Co-authored-by: Martin Aeschlimann <martinae@microsoft.com>

* Delete --compatibility=1.63 code from the server (#183738)

* Copy vscode.dev link to tunnel generates an invalid link when an untitled workspace is open (#183739)

* Recent devcontainer display string corrupted on Get Started page (#183740)

* Improve "next codeblock" navigation (#183744)

* Improve "next codeblock" navigation
Operate on the current focused response, or the last one, and scroll to the selected item

* Normalize command title

* Git - run git status if similarityThreshold changes (#183762)

* fix aria-label issue in kb editor

fixes A11y_GradeB_VSCode_Keyboard shortcut reads words together - Blind: Arrow key navigation to row Find the binding keys and  "when" cell data are read together resulting in a word " CTRL + FeditorFocus  instead of CTRL + F editorFocus" #182490

* Status - fix compact padding (#183768)

* Remove angle brackets from VB brackets (#183782)

Fixes #183359

* Update language config schema with more details about brackets. (#183779)

* fix comment (#183812)

* Support for `Notebook` CodeAction Kind (#183457)

* nb kind support -- wip

* allow notebook codeactions around single cell edit check

* move notebook code action type out of editor

---------

Co-authored-by: rebornix <penn.lv@gmail.com>

* cli: fix connection default being applied (#183827)

* cli: bump to openssl 1.1.1u (#183828)

* Implement "delete" action for chat history (#183609)

* Use desired file name when generating new md pasted file paths (#183861)

Fixes #183851

* Default to filename for markdown new file if empty (#183864)

Fixes #183848

* Fix small typo (#183865)

Fixes #183819

* Noop when moving a symbol into the file it is already in (#183866)

Fixes #183793

* Adjust codeAction validation to account for notebook kind (#183859)

* Make JS/TS `go to configuration` commands work on non-`file:` file systems (#183688)

Make `go to project` commands work on non-`file:` file systems

Fixes #183685

* Can't do regex search after opening notebook (#183884)

Fixes #183858

* Default to current dir for `move to file` select (#183875)

Fixes #183870

`showOpenDialog` seems to ignore `defaultUri` if the file doesn't exist

* Use `<...>` style markdown links when needed (#183876)

Fixes #183849

* Remove check for context keys

* Update xterm package

* Enable updating a chat model without triggering incremental typing (#183894)

* Enable chat "move" commands on empty sessions (#183895)

* Enable chat "move" commands on empty sessions
and also imported sessions

* Fix command name

* Fix some chat keybindings on windows (#183896)

* "Revert File" on inactive editors are ignored (fix #177557) (#183903)

* Empty reason while switching profile (fix #183775) (#183904)

* fix https://github.com/microsoft/vscode-internalbacklog/issues/4278 (#183910)

* fix https://github.com/microsoft/vscode/issues/183770 (#183914)

* code --status displays a lot of errors before actual status output (fix #183787) (#183915)

* joh/icy manatee (#183917)

* Use idle value for widget of interactive editor controller

https://github.com/microsoft/vscode/issues/183820

* also make preview editors idle values

https://github.com/microsoft/vscode/issues/183820

* Fix #183777 (#183929)

* Fix #182309 (#183925)

* Tree checkbox item -> items (#183931)

Fixes #183826

* Fixes #183909 (#183940)

* Fix #183837 (#183943)

fix #183837

* Git - fix #183941 (#183944)

* Update xterm.css

Fixes #181242

* chore: add @ulugbekna and @aiday-mar to my-endgame notebook (#183946)

* Revert "When snippet mode is active, make `Tab` not accept suggestion but advance placeholder"

This reverts commit 50a80cdb61511343996ff1d41d0b676c3d329f48.

* revert not focusing completion list when quick suggest happens during snippet

* change `snippetsPreventQuickSuggestions` default to false

* Fix #181446 (#183956)

* fix https://github.com/microsoft/vscode-internalbacklog/issues/4298 (#183957)

* fix: remove extraneous incorrect context keys (#183959)

These were actually getting added in getTestItemContextOverlay, and the test ID was using the extended ID which extensions do not know about.

Fixes #183612

* Fixes https://github.com/microsoft/monaco-editor/issues/3920 (#183960)

* fix https://github.com/microsoft/vscode-internalbacklog/issues/4324 (#183961)

* fix #183030

* fix #180826 (#183962)

* make message more generic for interactive editor help

* .

* fix #183968

* Keep codeblock toolbar visible when focused

* Fix when clause on "Run in terminal" command

* add important info to help menu

* fix #183970

* Set `isRefactoring` for all TS refactoring edits (#183982)

* consolidate

* Disable move to file in TS versions < 5.2 (#183992)

There are still a few key bugs with refactoring. We will  ship this as a preview for TS 5.2+ instead of for 5.1

* Polish query accepting (#183995)

We shouldn't send the same request to Copilot if the query hasn't changed. So if the query is the same, we short circut.

Fixes https://github.com/microsoft/vscode-internalbacklog/issues/4286

Also, when we open in chat, we should use the last accepted query, not what's in the input box.

Fixes https://github.com/microsoft/vscode-internalbacklog/issues/4280

* Allow widget to have focus (#184000)

So that selecting non-code text works.

Fixes https://github.com/microsoft/vscode-internalbacklog/issues/4294

* Fix microsoft/vscode-internalbacklog#4257. Mitigate zindex for zone widgets. (#184001)

* Change welcome dialog contribution to Eventually

* Misc fixes

* Workspace folder picker entry descriptions are suboptimal for some filesystems (fix #183418) (#184018)

* cli - ignore std error unless verbose (#183787) (#184031)

* joh/inquisitive meerkat (#184034)

* only stash sessions that are none empty

https://github.com/microsoft/vscode-internalbacklog/issues/4281

* only unstash a session once - unless new exchanges are made,

https://github.com/microsoft/vscode-internalbacklog/issues/4281

* account for all exchange types

* Improve declared components (#184039)

* make sure to read setting (#184040)

d'oh, related to https://github.com/microsoft/vscode/issues/173387#issuecomment-1571696644

* [html] update service (#184049)

[html] update service. FIxes #181176

* reset context keys on reset/hide (#184042)

fixes https://github.com/microsoft/vscode-internalbacklog/issues/4330

* use `Lazy`, not `IdleValue` for the IE widget held by the eager controller (#184048)

https://github.com/microsoft/vscode/issues/183820

* fix https://github.com/microsoft/vscode-internalbacklog/issues/4333 (#184067)

* use undo-loop instead of undo-edit when discarding chat session (#184063)

* use undo-loop instead of undo-edit when discarding chat session

fixes https://github.com/microsoft/vscode-internalbacklog/issues/4118

* fix tests, wait for correct state

* Add logging to node download (#184070)

Add logging to node download. For #182951

* re-enable default zone widget revealing when showing (#184072)

fixes https://github.com/microsoft/vscode-internalbacklog/issues/4332, also fixes https://github.com/microsoft/vscode-internalbacklog/issues/3784

* fix #178202

* Allow APIs in stable (#184062)

* Fix microsoft/vscode-internalbacklog#4206. Override List view whitespace css for monaco editor (#184087)

* Fix JSDoc grammatical error (#184090)

* Pick up TS 5.1.3 (#184091)

Fixes #182931

* Misc fixes

* update distro (#184097)

* chore: update electron@22.5.5 (#184116)

* Extension host veto is registered multiple times on restart (fix #183778) (#184127)

Extension host veto is registered multiple times on restart (#183778)

* Do not auto start the local web worker extension host (#184137)

* Allow embedders to intercept trustedTypes.createPolicy calls (#184136)

Allow embedders to intercept trustedTypes.createPolicy calls (#184100)

* fix: reading from console output for --status on windows and linux (#184138)

fix: reading from console output for --status on windows and linux (#184118)

* Misc fixes

* code --status displays a lot of errors before actual status output (fix #183787) (#184200)

fix 183787

* (cherry-pick to 1.79 from main) Handle galleryExtension failure in featuredExtensionService (#184205)

Handle galleryExtension failure in featuredExtensionService (#184198)

Handle galleryExtension failure

* Fix #184183. Multiple output height updates are skipped. (#184188)

* Post merge init fixes

* Misc build issues

* disable toggle inline diff of `alt` down

https://github.com/microsoft/vscode-internalbacklog/issues/4342

* Take into account already activated extensions when computing running locations (#184303)

Take into account already activated extensions when computing running locations (fixes #184180)

* Avoid `extensionService.getExtension` and use `ActivationKind.Immediate` to allow that URI handling works while resolving (#184310)

Avoid `extensionService.getExtension` and use `ActivationKind.Immediate` to allow that URI handling works while resolving (fixes #182217)

* WIP

* rm fish auto injection

* More breaks

* Fix Port Attributes constructor (#184412)

* WIP

* WIP

* Allow extensions to get at the exports of other extensions during resolving (#184487)

Allow extensions to get at the exports of other extensions during resolving (fixes #184472)

* do not auto finish session when inline chat widgets have focus

re https://github.com/microsoft/vscode-internalbacklog/issues/4354

* fix compile errors caused by new base method

* WIP

* WIP

* WIP

* WIP

* Build errors

* unc - fix path traversal bypass

* Bump version

* cherry-pick prod changes from main

* Disable sandbox

* Build break from merge

* bump version

* Merge pull request #184739 from max06/max06/issue184659

Restore ShellIntegration for fish (#184659)

* Git - only add --find-renames if the value is not the default one (#185053)

Git - only add --find-renames if the value is not the default one (#184992)

* Cherry-pick: Revert changes to render featured extensions when available (#184747)

Revert changes to render featured extensions when available.  (#184573)

* Lower timeouts for experimentation and gallery service

* Revert changes to render extensions when available

* Add audio cues

* fix: disable app sandbox when --no-sandbox is present (#184913)

* fix: disable app sandbox when --no-sandbox is present (#184897)

* fix: loading minimist in packaged builds

* Runtime errors

* UNC allow list checks cannot be disabled in extension host (fix #184989) (#185085)

* UNC allow list checks cannot be disabled in extension host (#184989)

* Update src/vs/base/node/unc.js

Co-authored-by: Robo <hop2deep@gmail.com>

---------

Co-authored-by: Robo <hop2deep@gmail.com>

* Add notebook extension

* Fix mangling issues

* Fix mangling issues

* npm install

* npm install

* Issues blocking bundle

* Fix build folder compile errors

* Fix windows bundle build

* Linting fixes

* Fix sqllint issues

* Update yarn.lock files

* Fix unit tests

* Fix a couple breaks from test fixes

* Bump distro

* redo the checkbox style

* Update linux build container dockerfile

* Bump build image tag

* Bump native watch dog package

* Bump node-pty

* Bump distro

* Fix documnetation error

* Update distro

* redo the button styles

* Update datasource TS

* Add missing yarn.lock files

* Windows setup fix

* Turn off extension unit tests while investigating

* color box style

* Remove appx

* Turn off test log upload

* update dropdownlist style

* fix universal app build error (#23488)

* Skip flaky bufferContext vscode test

---------

Co-authored-by: Johannes <johannes.rieken@gmail.com>
Co-authored-by: Henning Dieterichs <hdieterichs@microsoft.com>
Co-authored-by: Julien Richard <jairbubbles@hotmail.com>
Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
Co-authored-by: Megan Rogge <merogge@microsoft.com>
Co-authored-by: meganrogge <megan.rogge@microsoft.com>
Co-authored-by: Rob Lourens <roblourens@gmail.com>
Co-authored-by: Connor Peet <connor@peet.io>
Co-authored-by: Joyce Er <joyce.er@microsoft.com>
Co-authored-by: Bhavya U <bhavyau@microsoft.com>
Co-authored-by: Raymond Zhao <7199958+rzhao271@users.noreply.github.com>
Co-authored-by: Martin Aeschlimann <martinae@microsoft.com>
Co-authored-by: Aaron Munger <aamunger@microsoft.com>
Co-authored-by: Aiday Marlen Kyzy <amarlenkyzy@microsoft.com>
Co-authored-by: rebornix <penn.lv@gmail.com>
Co-authored-by: Ole <oler@google.com>
Co-authored-by: Jean Pierre <jeanp413@hotmail.com>
Co-authored-by: Robo <hop2deep@gmail.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
Co-authored-by: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com>
Co-authored-by: Ulugbek Abdullaev <ulugbekna@gmail.com>
Co-authored-by: Alex Ross <alros@microsoft.com>
Co-authored-by: Michael Lively <milively@microsoft.com>
Co-authored-by: Matt Bierner <matb@microsoft.com>
Co-authored-by: Andrea Mah <31675041+andreamah@users.noreply.github.com>
Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
Co-authored-by: Sandeep Somavarapu <sasomava@microsoft.com>
Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
Co-authored-by: Tyler James Leonhardt <me@tylerleonhardt.com>
Co-authored-by: Alexandru Dima <alexdima@microsoft.com>
Co-authored-by: Joao Moreno <Joao.Moreno@microsoft.com>
Co-authored-by: Alan Ren <alanren@microsoft.com>
This commit is contained in:
Karl Burtram
2023-06-27 15:26:51 -07:00
committed by GitHub
co-authored by Robo Johannes Henning Dieterichs Julien Richard Charles Gagnon Megan Rogge meganrogge Rob Lourens Connor Peet Joyce Er Bhavya U Raymond Zhao Martin Aeschlimann Aaron Munger Aiday Marlen Kyzy rebornix Ole Jean Pierre Yash Singh Ladislau Szomoru Ulugbek Abdullaev Alex Ross Michael Lively Matt Bierner Andrea Mah Benjamin Pasero Sandeep Somavarapu Daniel Imms Tyler James Leonhardt Alexandru Dima Joao Moreno Alan Ren
parent 7975fda6dd
commit 01e66ab3e6
4335 changed files with 252586 additions and 164604 deletions
+1
View File
@@ -116,3 +116,4 @@ function createAsar(folderPath, unpackGlobs, destFilename) {
});
}
exports.createAsar = createAsar;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFzYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsNkJBQTZCO0FBQzdCLG1DQUFtQztBQUNuQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQztBQUM3QyxNQUFNLFVBQVUsR0FBMEIsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFDekUsbUNBQW1DO0FBQ25DLHVDQUF1QztBQVN2QyxTQUFnQixVQUFVLENBQUMsVUFBa0IsRUFBRSxXQUFxQixFQUFFLFlBQW9CO0lBRXpGLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxJQUFlLEVBQVcsRUFBRTtRQUNyRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM1QyxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUM3QyxPQUFPLElBQUksQ0FBQzthQUNaO1NBQ0Q7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNkLENBQUMsQ0FBQztJQUVGLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLE1BQU0sR0FBRyxHQUFhLEVBQUUsQ0FBQztJQUV6QixnQ0FBZ0M7SUFDaEMsSUFBSSxjQUFjLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLElBQUksY0FBYyxHQUFHLEdBQUcsRUFBRSxHQUFHLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRWpELHlDQUF5QztJQUN6QyxNQUFNLE9BQU8sR0FBK0IsRUFBRSxDQUFDO0lBQy9DLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRTtRQUNoRCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUNqQixPQUFPO1NBQ1A7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
File diff suppressed because one or more lines are too long
+18 -3
View File
@@ -68,10 +68,26 @@ function isUpToDate(extension: IExtensionDefinition): boolean {
}
}
function getExtensionDownloadStream(extension: IExtensionDefinition) {
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension))
.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([]);
@@ -79,8 +95,7 @@ function syncMarketplaceExtension(extension: IExtensionDefinition): Stream {
rimraf.sync(getExtensionPath(extension));
return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension))
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`))
return getExtensionDownloadStream(extension)
.pipe(vfs.dest('.build/builtInExtensions'))
.on('end', () => log(source, extension.name, ansiColors.green('✔︎')));
}
+20 -18
View File
@@ -4,7 +4,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const got_1 = require("got");
const node_fetch_1 = require("node-fetch");
const fs = require("fs");
const path = require("path");
const url = require("url");
@@ -14,30 +14,31 @@ 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['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || undefined;
const token = process.env['GITHUB_TOKEN'];
const contentBasePath = 'raw.githubusercontent.com';
const contentFileNames = ['package.json', 'package-lock.json', 'yarn.lock'];
async function downloadExtensionDetails(extension) {
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}`;
const promises = [];
for (const fileName of contentFileNames) {
promises.push(new Promise(resolve => {
(0, got_1.default)(`${repositoryContentBaseUrl}/${fileName}`)
.then(response => {
resolve({ fileName, body: response.rawBody });
})
.catch(error => {
if (error.response.statusCode === 404) {
resolve({ fileName, body: undefined });
}
else {
resolve({ fileName, body: null });
}
});
}));
async function getContent(fileName) {
try {
const response = await (0, node_fetch_1.default)(`${repositoryContentBaseUrl}/${fileName}`);
if (response.ok) {
return { fileName, body: await response.buffer() };
}
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) {
@@ -76,3 +77,4 @@ main().then(() => {
console.error(err);
process.exit(1);
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbHRJbkV4dGVuc2lvbnNDRy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImJ1aWx0SW5FeHRlbnNpb25zQ0cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOztBQUVoRywyQ0FBK0I7QUFDL0IseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QiwyQkFBMkI7QUFDM0IsMENBQTJDO0FBRzNDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQ25ELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0FBQy9DLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDcEcsTUFBTSxpQkFBaUIsR0FBMkIsV0FBVyxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQztBQUN0RixNQUFNLG9CQUFvQixHQUEyQixXQUFXLENBQUMsb0JBQW9CLElBQUksRUFBRSxDQUFDO0FBQzVGLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7QUFFMUMsTUFBTSxlQUFlLEdBQUcsMkJBQTJCLENBQUM7QUFDcEQsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUU1RSxLQUFLLFVBQVUsd0JBQXdCLENBQUMsU0FBK0I7SUFDdEUsTUFBTSxjQUFjLEdBQUcsR0FBRyxTQUFTLENBQUMsSUFBSSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNoRSxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJ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
+18 -17
View File
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import got from 'got';
import fetch from 'node-fetch';
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
@@ -15,7 +15,7 @@ const rootCG = path.join(root, 'extensionsCG');
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = <IExtensionDefinition[]>productjson.builtInExtensions || [];
const webBuiltInExtensions = <IExtensionDefinition[]>productjson.webBuiltInExtensions || [];
const token = process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || undefined;
const token = process.env['GITHUB_TOKEN'];
const contentBasePath = 'raw.githubusercontent.com';
const contentFileNames = ['package.json', 'package-lock.json', 'yarn.lock'];
@@ -25,23 +25,24 @@ async function downloadExtensionDetails(extension: IExtensionDefinition): Promis
const repository = url.parse(extension.repo).path!.substr(1);
const repositoryContentBaseUrl = `https://${token ? `${token}@` : ''}${contentBasePath}/${repository}/v${extension.version}`;
const promises = [];
for (const fileName of contentFileNames) {
promises.push(new Promise<{ fileName: string; body: Buffer | undefined | null }>(resolve => {
got(`${repositoryContentBaseUrl}/${fileName}`)
.then(response => {
resolve({ fileName, body: response.rawBody });
})
.catch(error => {
if (error.response.statusCode === 404) {
resolve({ fileName, body: undefined });
} else {
resolve({ fileName, body: null });
}
});
}));
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: await response.buffer() };
} 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) {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+48 -14
View File
@@ -19,9 +19,13 @@ import * as os from 'os';
import ts = require('typescript');
import * as File from 'vinyl';
import * as task from './task';
// import { Mangler } from './mangleTypeScript';
// import { RawSourceMap } from 'source-map';
const watch = require('./watch');
// --- gulp-tsb: compile and transpile --------------------------------
const reporter = createReporter();
function getTypeScriptCompilerOptions(src: string): ts.CompilerOptions {
@@ -39,7 +43,7 @@ function getTypeScriptCompilerOptions(src: string): ts.CompilerOptions {
return options;
}
function createCompile(src: string, build: boolean, emitError: boolean, transpileOnly: boolean) {
function createCompile(src: string, build: boolean, emitError: boolean, transpileOnly: boolean | { swc: boolean }) {
const tsb = require('./tsb') as typeof import('./tsb');
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
@@ -60,31 +64,35 @@ function createCompile(src: string, build: boolean, emitError: boolean, transpil
}
const compilation = tsb.create(projectPath, overrideOptions, { verbose: false, transpileOnly }, err => reporter(err));
const compilation = tsb.create(projectPath, overrideOptions, {
verbose: false,
transpileOnly: Boolean(transpileOnly),
transpileWithSwc: typeof transpileOnly !== 'boolean' && transpileOnly.swc
}, err => reporter(err));
function pipeline(token?: util.ICancellationToken) {
const bom = require('gulp-bom') as typeof import('gulp-bom');
const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path));
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 noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path)));
const input = es.through();
const output = input
.pipe(utf8Filter)
.pipe(bom()) // this is required to preserve BOM in test files that loose it otherwise
.pipe(utf8Filter.restore)
.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(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(compilation(token))
.pipe(noDeclarationsFilter)
.pipe(build ? nls.nls() : es.through())
.pipe(util.$if(build, nls.nls()))
.pipe(noDeclarationsFilter.restore)
.pipe(transpileOnly ? es.through() : sourcemaps.write('.', {
.pipe(util.$if(!transpileOnly, sourcemaps.write('.', {
addComment: false,
includeContent: !!build,
sourceRoot: overrideOptions.sourceRoot
}))
})))
.pipe(tsFilter.restore)
.pipe(reporter.end(!!emitError));
@@ -93,14 +101,15 @@ function createCompile(src: string, build: boolean, emitError: boolean, transpil
pipeline.tsProjectSrc = () => {
return compilation.src({ base: src });
};
pipeline.projectPath = projectPath;
return pipeline;
}
export function transpileTask(src: string, out: string): () => NodeJS.ReadWriteStream {
export function transpileTask(src: string, out: string, swc: boolean): () => NodeJS.ReadWriteStream {
return function () {
const transpile = createCompile(src, false, true, true);
const transpile = createCompile(src, false, true, { swc });
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
return srcPipe
@@ -109,10 +118,12 @@ export function transpileTask(src: string, out: string): () => NodeJS.ReadWriteS
};
}
export function compileTask(src: string, out: string, build: boolean): () => NodeJS.ReadWriteStream {
export function compileTask(src: string, out: string, build: boolean, options: { disableMangle?: boolean } = {}): () => NodeJS.ReadWriteStream {
return function () {
options.disableMangle = true; // {{SQL CARBON EDIT}} - disable mangling
if (os.totalmem() < 4_000_000_000) {
throw new Error('compilation requires 4GB of RAM');
}
@@ -124,7 +135,30 @@ export function compileTask(src: string, out: string, build: boolean): () => Nod
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));
// const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState']));
// mangleStream = es.through(function write(data: File & { sourceMap?: RawSourceMap }) {
// type TypeScriptExt = typeof ts & { normalizePath(path: string): string };
// const tsNormalPath = (<TypeScriptExt>ts).normalizePath(data.path);
// const newContents = newContentsByFileName.get(tsNormalPath);
// if (newContents !== undefined) {
// data.contents = Buffer.from(newContents.out);
// data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap);
// }
// this.push(data);
// }, function end() {
// this.push(null);
// // free resources
// newContentsByFileName.clear();
// (<any>ts2tsMangler) = undefined;
// });
// }
return srcPipe
//.pipe(mangleStream)
.pipe(generator.stream)
.pipe(compile())
.pipe(gulp.dest(out));
@@ -272,7 +306,7 @@ function generateApiProposalNames() {
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
'',
'export const allApiProposals = Object.freeze({',
`${names.map(name => `\t${name}: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.${name}.d.ts'`).join(`,${os.EOL}`)}`,
`${names.map(name => `\t${name}: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.${name}.d.ts'`).join(`,${eol}`)}`,
'});',
'export type ApiProposalName = keyof typeof allApiProposals;',
'',
+24 -8
View File
@@ -5,10 +5,11 @@
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getProductionDependencies = void 0;
const fs = require("fs");
const path = require("path");
const cp = require("child_process");
const _ = require("underscore");
const parseSemver = require('parse-semver');
const root = fs.realpathSync(path.dirname(path.dirname(__dirname)));
function asYarnDependency(prefix, tree) {
let parseResult;
try {
@@ -35,26 +36,41 @@ function asYarnDependency(prefix, tree) {
}
return { name, version, path: dependencyPath, children };
}
function getYarnProductionDependencies(cwd) {
const raw = cp.execSync('yarn list --json', { cwd, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'inherit'] });
function getYarnProductionDependencies(folderPath) {
const raw = cp.execSync('yarn list --json', { cwd: folderPath, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'inherit'] });
const match = /^{"type":"tree".*$/m.exec(raw);
if (!match || match.length !== 1) {
throw new Error('Could not parse result of `yarn list --json`');
}
const trees = JSON.parse(match[0]).data.trees;
return trees
.map(tree => asYarnDependency(path.join(cwd, 'node_modules'), tree))
.map(tree => asYarnDependency(path.join(folderPath, 'node_modules'), tree))
.filter((dep) => !!dep);
}
function getProductionDependencies(cwd) {
function getProductionDependencies(folderPath) {
const result = [];
const deps = getYarnProductionDependencies(cwd);
const deps = getYarnProductionDependencies(folderPath);
const flatten = (dep) => { result.push({ name: dep.name, version: dep.version, path: dep.path }); dep.children.forEach(flatten); };
deps.forEach(flatten);
return _.uniq(result);
// Account for distro npm dependencies
const realFolderPath = fs.realpathSync(folderPath);
const relativeFolderPath = path.relative(root, realFolderPath);
const distroPackageJsonPath = `${root}/.build/distro/npm/${relativeFolderPath}/package.json`;
if (fs.existsSync(distroPackageJsonPath)) {
const distroPackageJson = JSON.parse(fs.readFileSync(distroPackageJsonPath, 'utf8'));
const distroDependencyNames = Object.keys(distroPackageJson.dependencies ?? {});
for (const name of distroDependencyNames) {
result.push({
name,
version: distroPackageJson.dependencies[name],
path: path.join(realFolderPath, 'node_modules', name)
});
}
}
return [...new Set(result)];
}
exports.getProductionDependencies = getProductionDependencies;
if (require.main === module) {
const root = path.dirname(path.dirname(__dirname));
console.log(JSON.stringify(getProductionDependencies(root), null, ' '));
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jaWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwZW5kZW5jaWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0Isb0NBQW9DO0FBQ3BDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUM1QyxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFpQnBFLFNBQVMsZ0JBQWdCLENBQUMsTUFBYyxFQUFFLElBQVU7SUFDbkQsSUFBSSxXQUFXLENBQUM7SUFFaEIsSUFBSTtRQUNILFdBQVcsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ3JDO0lBQUMsT0FBTyxHQUFHLEVBQUU7UUFDYixHQUFHLENBQUMsT0FBTyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hDLE9BQU8sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELE9BQU8sSUFBSSxDQUFDO0tBQ1o7SUFFRCxtQ0FBbUM7SUFDbkMsSUFBSSxXQUFXLENBQUMsT0FBTyxLQUFLLFdBQVcsQ0FBQyxLQUFLLEVBQUU7UUFDOUMsT0FBTyxJQUFJLENBQUM7S0FDWjtJQUVELE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUM7SUFDOUIsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQztJQUNwQyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUMvQyxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFFcEIsS0FBSyxNQUFNLEtBQUssSUFBSSxD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
+27 -8
View File
@@ -3,10 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import * as path from 'path';
import * as cp from 'child_process';
import * as _ from 'underscore';
const parseSemver = require('parse-semver');
const root = fs.realpathSync(path.dirname(path.dirname(__dirname)));
interface Tree {
readonly name: string;
@@ -55,8 +56,8 @@ function asYarnDependency(prefix: string, tree: Tree): Dependency | null {
return { name, version, path: dependencyPath, children };
}
function getYarnProductionDependencies(cwd: string): Dependency[] {
const raw = cp.execSync('yarn list --json', { cwd, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'inherit'] });
function getYarnProductionDependencies(folderPath: string): Dependency[] {
const raw = cp.execSync('yarn list --json', { cwd: folderPath, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'inherit'] });
const match = /^{"type":"tree".*$/m.exec(raw);
if (!match || match.length !== 1) {
@@ -66,19 +67,37 @@ function getYarnProductionDependencies(cwd: string): Dependency[] {
const trees = JSON.parse(match[0]).data.trees as Tree[];
return trees
.map(tree => asYarnDependency(path.join(cwd, 'node_modules'), tree))
.map(tree => asYarnDependency(path.join(folderPath, 'node_modules'), tree))
.filter<Dependency>((dep): dep is Dependency => !!dep);
}
export function getProductionDependencies(cwd: string): FlatDependency[] {
export function getProductionDependencies(folderPath: string): FlatDependency[] {
const result: FlatDependency[] = [];
const deps = getYarnProductionDependencies(cwd);
const deps = getYarnProductionDependencies(folderPath);
const flatten = (dep: Dependency) => { result.push({ name: dep.name, version: dep.version, path: dep.path }); dep.children.forEach(flatten); };
deps.forEach(flatten);
return _.uniq(result);
// Account for distro npm dependencies
const realFolderPath = fs.realpathSync(folderPath);
const relativeFolderPath = path.relative(root, realFolderPath);
const distroPackageJsonPath = `${root}/.build/distro/npm/${relativeFolderPath}/package.json`;
if (fs.existsSync(distroPackageJsonPath)) {
const distroPackageJson = JSON.parse(fs.readFileSync(distroPackageJsonPath, 'utf8'));
const distroDependencyNames = Object.keys(distroPackageJson.dependencies ?? {});
for (const name of distroDependencyNames) {
result.push({
name,
version: distroPackageJson.dependencies[name],
path: path.join(realFolderPath, 'node_modules', name)
});
}
}
return [...new Set(result)];
}
if (require.main === module) {
const root = path.dirname(path.dirname(__dirname));
console.log(JSON.stringify(getProductionDependencies(root), null, ' '));
}
File diff suppressed because one or more lines are too long
+8 -7
View File
@@ -9,6 +9,7 @@ import * as vfs from 'vinyl-fs';
import * as filter from 'gulp-filter';
import * as _ from 'underscore';
import * as util from './util';
import { getVersion } from './getVersion';
type DarwinDocumentSuffix = 'document' | 'script' | 'file' | 'source code';
type DarwinDocumentType = {
@@ -26,7 +27,7 @@ function isDocumentSuffix(str?: string): str is DarwinDocumentSuffix {
const root = path.dirname(path.dirname(__dirname));
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
const commit = util.getVersion(root);
const commit = getVersion(root);
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
@@ -91,10 +92,10 @@ function darwinBundleDocumentType(extensions: string[], icon: string, nameOrSuff
// }
export const config = {
version: util.getElectronVersion(),
version: product.electronRepository ? '22.5.7' : util.getElectronVersion(),
productAppName: product.nameLong,
companyName: 'Microsoft Corporation',
copyright: 'Copyright (C) 2022 Microsoft. All rights reserved',
copyright: 'Copyright (C) 2023 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools',
@@ -112,19 +113,19 @@ export const config = {
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : undefined,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || undefined,
token: process.env['GITHUB_TOKEN'],
repo: product.electronRepository || undefined
};
function getElectron(arch: string): () => NodeJS.ReadWriteStream {
return () => {
const electron = require('gulp-atom-electron');
const electron = require('@vscode/gulp-electron');
const json = require('gulp-json-editor') as typeof import('gulp-json-editor');
const electronOpts = _.extend({}, config, {
platform: process.platform,
arch: arch === 'armhf' ? 'arm' : arch,
ffmpegChromium: true,
ffmpegChromium: false,
keepDefaultApp: true
});
@@ -137,7 +138,7 @@ function getElectron(arch: string): () => NodeJS.ReadWriteStream {
}
async function main(arch = process.arch): Promise<void> {
const version = util.getElectronVersion();
const version = product.electronRepository ? '22.5.7' : util.getElectronVersion();
const electronPath = path.join(root, '.build', 'electron');
const versionFile = path.join(electronPath, 'version');
const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`;
-199
View File
@@ -1,199 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path = require("path");
const minimatch = require("minimatch");
const utils_1 = require("./utils");
const REPO_ROOT = path.normalize(path.join(__dirname, '../../../'));
function isLayerAllowRule(option) {
return !!(option.when && option.allow);
}
/**
* Returns the filename relative to the project root and using `/` as separators
*/
function getRelativeFilename(context) {
const filename = path.normalize(context.getFilename());
return filename.substring(REPO_ROOT.length).replace(/\\/g, '/');
}
module.exports = new class {
constructor() {
this.meta = {
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/.eslintrc.json'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
}
};
this._optionsCache = new WeakMap();
}
create(context) {
const options = context.options;
const configs = this._processOptions(options);
const relativeFilename = getRelativeFilename(context);
for (const config of configs) {
if (minimatch(relativeFilename, config.target)) {
return (0, utils_1.createImportRuleListener)((node, value) => this._checkImport(context, config, node, value));
}
}
context.report({
loc: { line: 1, column: 0 },
messageId: 'badFilename'
});
return {};
}
_processOptions(options) {
if (this._optionsCache.has(options)) {
return this._optionsCache.get(options);
}
function orSegment(variants) {
return (variants.length === 1 ? variants[0] : `{${variants.join(',')}}`);
}
const layerRules = [
{ 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-browser', deps: orSegment(['common', 'browser', 'node', 'electron-sandbox', 'electron-browser']), isBrowser: true, isNode: true },
{ layer: 'electron-main', deps: orSegment(['common', 'node', 'electron-main']), isNode: true },
];
let browserAllow = [];
let nodeAllow = [];
let testAllow = [];
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 === 'test') {
testAllow = option.allow.slice(0);
}
}
}
function findLayer(layer) {
for (const layerRule of layerRules) {
if (layerRule.layer === layer) {
return layerRule;
}
}
return null;
}
function generateConfig(layerRule, target, rawRestrictions) {
const restrictions = [];
const testRestrictions = [...testAllow];
if (layerRule.isBrowser) {
restrictions.push(...browserAllow);
}
if (layerRule.isNode) {
restrictions.push(...nodeAllow);
}
for (const rawRestriction of rawRestrictions) {
let importPattern;
let when = 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)) {
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 = [];
for (const option of options) {
if (isLayerAllowRule(option)) {
continue;
}
const target = option.target;
const targetIsVS = /^src\/{vs,sql}\//.test(target);
const restrictions = (typeof option.restrictions === 'string' ? [option.restrictions] : option.restrictions).slice(0);
if (targetIsVS) {
// Always add "vs/nls"
restrictions.push('vs/nls');
}
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;
}
_checkImport(context, config, node, importPath) {
// resolve relative paths
if (importPath[0] === '.') {
const relativeFilename = getRelativeFilename(context);
importPath = path.posix.join(path.posix.dirname(relativeFilename), importPath);
if (/^src\/{vs,sql}\//.test(importPath)) {
// resolve using AMD 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 ')
}
});
}
}
};
-255
View File
@@ -1,255 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-utils';
import * as path from 'path';
import * as minimatch from 'minimatch';
import { createImportRuleListener } from './utils';
const REPO_ROOT = path.normalize(path.join(__dirname, '../../../'));
interface ConditionalPattern {
when?: 'hasBrowser' | 'hasNode' | 'test';
pattern: string;
}
interface RawImportPatternsConfig {
target: string;
layer?: 'common' | 'worker' | 'browser' | 'electron-sandbox' | 'node' | 'electron-browser' | 'electron-main';
test?: boolean;
restrictions: string | (string | ConditionalPattern)[];
}
interface LayerAllowRule {
when: 'hasBrowser' | 'hasNode' | 'test';
allow: string[];
}
type RawOption = RawImportPatternsConfig | LayerAllowRule;
function isLayerAllowRule(option: RawOption): option is LayerAllowRule {
return !!((<LayerAllowRule>option).when && (<LayerAllowRule>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/.eslintrc.json'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const options = <RawOption[]>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<RawOption[], ImportPatternsConfig[]>();
private _processOptions(options: RawOption[]): ImportPatternsConfig[] {
if (this._optionsCache.has(options)) {
return this._optionsCache.get(options)!;
}
type Layer = 'common' | 'worker' | 'browser' | 'electron-sandbox' | 'node' | 'electron-browser' | 'electron-main';
interface ILayerRule {
layer: Layer;
deps: string;
isBrowser?: boolean;
isNode?: 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-browser', deps: orSegment(['common', 'browser', 'node', 'electron-sandbox', 'electron-browser']), isBrowser: true, isNode: true },
{ layer: 'electron-main', deps: orSegment(['common', 'node', 'electron-main']), isNode: true },
];
let browserAllow: string[] = [];
let nodeAllow: 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 === '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);
}
for (const rawRestriction of rawRestrictions) {
let importPattern: string;
let when: 'hasBrowser' | 'hasNode' | '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)
) {
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,sql}\//.test(target);
const restrictions = (typeof option.restrictions === 'string' ? [option.restrictions] : option.restrictions).slice(0);
if (targetIsVS) {
// Always add "vs/nls"
restrictions.push('vs/nls');
}
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: <string[]>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) {
// resolve relative paths
if (importPath[0] === '.') {
const relativeFilename = getRelativeFilename(context);
importPath = path.posix.join(path.posix.dirname(relativeFilename), importPath);
if (/^src\/{vs,sql}\//.test(importPath)) {
// resolve using AMD 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, '/');
}
-68
View File
@@ -1,68 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const utils_1 = require("./utils");
module.exports = new class {
constructor() {
this.meta = {
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'
}
};
}
create(context) {
const fileDirname = (0, path_1.dirname)(context.getFilename());
const parts = fileDirname.split(/\\|\//);
const ruleArgs = context.options[0];
let config;
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 (0, utils_1.createImportRuleListener)((node, path) => {
if (path[0] === '.') {
path = (0, path_1.join)((0, path_1.dirname)(context.getFilename()), path);
}
const parts = (0, path_1.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;
}
}
});
}
};
-83
View File
@@ -1,83 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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<string>;
disallowed: Set<string>;
};
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'
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const fileDirname = dirname(context.getFilename());
const parts = fileDirname.split(/\\|\//);
const ruleArgs = <Record<string, string[]>>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;
}
}
});
}
};
@@ -1,42 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const _positiveLookBehind = /\(\?<=.+/;
const _negativeLookBehind = /\(\?<!.+/;
function _containsLookBehind(pattern) {
if (typeof pattern !== 'string') {
return false;
}
return _positiveLookBehind.test(pattern) || _negativeLookBehind.test(pattern);
}
module.exports = {
create(context) {
return {
// /.../
['Literal[regex]']: (node) => {
const pattern = node.regex?.pattern;
if (_containsLookBehind(pattern)) {
context.report({
node,
message: 'Look behind assertions are not yet supported in all browsers'
});
}
},
// new Regex("...")
['NewExpression[callee.name="RegExp"] Literal']: (node) => {
if (_containsLookBehind(node.value)) {
context.report({
node,
message: 'Look behind assertions are not yet supported in all browsers'
});
}
}
};
}
};
@@ -1,50 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-utils';
import * as ESTree from 'estree';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const _positiveLookBehind = /\(\?<=.+/;
const _negativeLookBehind = /\(\?<!.+/;
function _containsLookBehind(pattern: string | unknown): boolean {
if (typeof pattern !== 'string') {
return false;
}
return _positiveLookBehind.test(pattern) || _negativeLookBehind.test(pattern);
}
module.exports = {
create(context: eslint.Rule.RuleContext) {
return {
// /.../
['Literal[regex]']: (node: any) => {
type RegexLiteral = TSESTree.Literal & { regex: { pattern: string; flags: string } };
const pattern = (<RegexLiteral>node).regex?.pattern;
if (_containsLookBehind(pattern)) {
context.report({
node,
message: 'Look behind assertions are not yet supported in all browsers'
});
}
},
// new Regex("...")
['NewExpression[callee.name="RegExp"] Literal']: (node: ESTree.Literal) => {
if (_containsLookBehind(node.value)) {
context.report({
node,
message: 'Look behind assertions are not yet supported in all browsers'
});
}
}
};
}
};
@@ -1,38 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const utils_1 = require("./utils");
module.exports = new class NoNlsInStandaloneEditorRule {
constructor() {
this.meta = {
messages: {
noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts'
}
};
}
create(context) {
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/.test(fileName)) {
return (0, utils_1.createImportRuleListener)((node, path) => {
// resolve relative paths
if (path[0] === '.') {
path = (0, path_1.join)(context.getFilename(), path);
}
if (/vs(\/|\\)nls/.test(path)) {
context.report({
loc: node.loc,
messageId: 'noNls'
});
}
});
}
return {};
}
};
@@ -1,48 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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'
}
};
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/.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 {};
}
};
@@ -1,41 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const utils_1 = require("./utils");
module.exports = new class NoNlsInStandaloneEditorRule {
constructor() {
this.meta = {
messages: {
badImport: 'Not allowed to import standalone editor modules.'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
}
};
}
create(context) {
if (/vs(\/|\\)editor/.test(context.getFilename())) {
// the vs/editor folder is allowed to use the standalone editor
return {};
}
return (0, utils_1.createImportRuleListener)((node, path) => {
// resolve relative paths
if (path[0] === '.') {
path = (0, path_1.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/.test(path)) {
context.report({
loc: node.loc,
messageId: 'badImport'
});
}
});
}
};
@@ -1,50 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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'
}
};
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/.test(path)
) {
context.report({
loc: node.loc,
messageId: 'badImport'
});
}
});
}
};
-17
View File
@@ -1,17 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class NoTestOnly {
create(context) {
return {
['MemberExpression[object.name="test"][property.name="only"]']: (node) => {
return context.report({
node,
message: 'test.only is a dev-time tool and CANNOT be pushed'
});
}
};
}
};
-20
View File
@@ -1,20 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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"][property.name="only"]']: (node: any) => {
return context.report({
node,
message: 'test.only is a dev-time tool and CANNOT be pushed'
});
}
};
}
};
@@ -1,111 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
function isStringLiteral(node) {
return !!node && node.type === experimental_utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'string';
}
function isDoubleQuoted(node) {
return node.raw[0] === '"' && node.raw[node.raw.length - 1] === '"';
}
module.exports = new (_a = class NoUnexternalizedStrings {
constructor() {
this.meta = {
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.'
}
};
}
create(context) {
const externalizedStringLiterals = new Map();
const doubleQuotedStringLiterals = new Set();
function collectDoubleQuotedStrings(node) {
if (isStringLiteral(node) && isDoubleQuoted(node)) {
doubleQuotedStringLiterals.add(node);
}
}
function visitLocalizeCall(node) {
// localize(key, message)
const [keyNode, messageNode] = node.arguments;
// (1)
// extract key so that it can be checked later
let key;
if (isStringLiteral(keyNode)) {
doubleQuotedStringLiterals.delete(keyNode);
key = keyNode.value;
}
else if (keyNode.type === experimental_utils_1.AST_NODE_TYPES.ObjectExpression) {
for (const property of keyNode.properties) {
if (property.type === experimental_utils_1.AST_NODE_TYPES.Property && !property.computed) {
if (property.key.type === experimental_utils_1.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 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) => collectDoubleQuotedStrings(node),
['ExpressionStatement[directive] Literal:exit']: (node) => doubleQuotedStringLiterals.delete(node),
['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize"]:exit']: (node) => visitLocalizeCall(node),
['CallExpression[callee.name="localize"][arguments.length>=2]:exit']: (node) => visitLocalizeCall(node),
['Program:exit']: reportBadStringsAndBadKeys,
};
}
},
_a._rNlsKeys = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/,
_a);
@@ -1,125 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-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.'
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const externalizedStringLiterals = new Map<string, { call: TSESTree.CallExpression; message: TSESTree.Node }[]>();
const doubleQuotedStringLiterals = new Set<TSESTree.Node>();
function collectDoubleQuotedStrings(node: TSESTree.Literal) {
if (isStringLiteral(node) && isDoubleQuoted(node)) {
doubleQuotedStringLiterals.add(node);
}
}
function visitLocalizeCall(node: TSESTree.CallExpression) {
// localize(key, message)
const [keyNode, messageNode] = (<TSESTree.CallExpression>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(<any>node) }
});
}
}
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(<any>values[i - 1].message) !== context.getSourceCode().getText(<any>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),
['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize"]:exit']: (node: any) => visitLocalizeCall(node),
['CallExpression[callee.name="localize"][arguments.length>=2]:exit']: (node: any) => visitLocalizeCall(node),
['Program:exit']: reportBadStringsAndBadKeys,
};
}
};
@@ -1,119 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
//------------------------------------------------------------------------------
// 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) {
const config = context.options[0] || {}, allowShortCircuit = config.allowShortCircuit || false, allowTernary = config.allowTernary || false, allowTaggedTemplates = config.allowTaggedTemplates || false;
// eslint-disable-next-line jsdoc/require-description
/**
* @param node any node
* @returns whether the given node structurally represents a directive
*/
function looksLikeDirective(node) {
return node.type === 'ExpressionStatement' &&
node.expression.type === 'Literal' && typeof node.expression.value === 'string';
}
// eslint-disable-next-line jsdoc/require-description
/**
* @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, list) {
for (let i = 0; i < list.length; ++i) {
if (!predicate(list[i])) {
return list.slice(0, i);
}
}
return list.slice();
}
// eslint-disable-next-line jsdoc/require-description
/**
* @param node a Program or BlockStatement node
* @returns the leading sequence of directive nodes in the given node's body
*/
function directives(node) {
return takeWhile(looksLikeDirective, node.body);
}
// eslint-disable-next-line jsdoc/require-description
/**
* @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, ancestors) {
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) {
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) {
if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) {
context.report({ node: node, message: `Expected an assignment or function call and instead saw an expression. ${node.expression}` });
}
}
};
}
};
@@ -1,151 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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/experimental-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;
// eslint-disable-next-line jsdoc/require-description
/**
* @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';
}
// eslint-disable-next-line jsdoc/require-description
/**
* @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<T>(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();
}
// eslint-disable-next-line jsdoc/require-description
/**
* @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);
}
// eslint-disable-next-line jsdoc/require-description
/**
* @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, <TSESTree.Node[]>context.getAncestors())) {
context.report({ node: <ESTree.Node>node, message: `Expected an assignment or function call and instead saw an expression. ${node.expression}` });
}
}
};
}
};
@@ -1,57 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
const fs_1 = require("fs");
const utils_1 = require("./utils");
module.exports = new (_a = class TranslationRemind {
constructor() {
this.meta = {
messages: {
missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.'
}
};
}
create(context) {
return (0, utils_1.createImportRuleListener)((node, path) => this._checkImport(context, node, path));
}
_checkImport(context, node, path) {
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 = (0, fs_1.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) => {
if (existingResource.name === resource) {
resourceDefined = true;
return;
}
});
if (!resourceDefined) {
context.report({
loc: node.loc,
messageId: 'missing',
data: { resource }
});
}
}
},
_a.NLS_MODULE = 'vs/nls',
_a);
@@ -1,67 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-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.'
}
};
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 }
});
}
}
};
-37
View File
@@ -1,37 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createImportRuleListener = void 0;
function createImportRuleListener(validateImport) {
function _checkImport(node) {
if (node && node.type === 'Literal' && typeof node.value === 'string') {
validateImport(node, node.value);
}
}
return {
// import ??? from 'module'
ImportDeclaration: (node) => {
_checkImport(node.source);
},
// import('module').then(...) OR await import('module')
['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node) => {
_checkImport(node);
},
// import foo = ...
['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node) => {
_checkImport(node);
},
// export ?? from 'module'
ExportAllDeclaration: (node) => {
_checkImport(node.source);
},
// export {foo} from 'module'
ExportNamedDeclaration: (node) => {
_checkImport(node.source);
},
};
}
exports.createImportRuleListener = createImportRuleListener;
-40
View File
@@ -1,40 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-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((<TSESTree.ImportDeclaration>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((<TSESTree.ExportAllDeclaration>node).source);
},
// export {foo} from 'module'
ExportNamedDeclaration: (node: any) => {
_checkImport((<TSESTree.ExportNamedDeclaration>node).source);
},
};
}
@@ -1,33 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
module.exports = new class ApiProviderNaming {
constructor() {
this.meta = {
messages: {
noToken: 'Function lacks a cancellation token, preferable as last argument',
}
};
}
create(context) {
return {
['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature[key.name=/^(provide|resolve).+/]']: (node) => {
let found = false;
for (const param of node.params) {
if (param.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
found = found || param.name === 'token';
}
}
if (!found) {
context.report({
node,
messageId: 'noToken'
});
}
}
};
}
};
@@ -1,38 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/experimental-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',
}
};
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 (<TSESTree.TSMethodSignature>node).params) {
if (param.type === AST_NODE_TYPES.Identifier) {
found = found || param.name === 'token';
}
}
if (!found) {
context.report({
node,
messageId: 'noToken'
});
}
}
};
}
};
@@ -1,34 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
module.exports = new class ApiLiteralOrTypes {
constructor() {
this.meta = {
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', }
};
}
create(context) {
return {
['TSDeclareFunction Identifier[name=/create.*/]']: (node) => {
const decl = node.parent;
if (decl.returnType?.typeAnnotation.type !== experimental_utils_1.AST_NODE_TYPES.TSTypeReference) {
return;
}
if (decl.returnType.typeAnnotation.typeName.type !== experimental_utils_1.AST_NODE_TYPES.Identifier) {
return;
}
const ident = decl.returnType.typeAnnotation.typeName.name;
if (ident === 'Promise' || ident === 'Thenable') {
context.report({
node,
messageId: 'sync'
});
}
}
};
}
};
@@ -1,40 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-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', }
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSDeclareFunction Identifier[name=/create.*/]']: (node: any) => {
const decl = <TSESTree.FunctionDeclaration>(<TSESTree.Identifier>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'
});
}
}
};
}
};
@@ -1,86 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
module.exports = new (_a = class ApiEventNaming {
constructor() {
this.meta = {
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><Subject>`',
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'
}
};
}
create(context) {
const config = context.options[0];
const allowed = new Set(config.allowed);
const verbs = new Set(config.verbs);
return {
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => {
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 <verb> 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] }
});
}
}
}
};
}
getIdent(def) {
if (!def) {
return;
}
if (def.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
return def;
}
else if ((def.type === experimental_utils_1.AST_NODE_TYPES.TSPropertySignature || def.type === experimental_utils_1.AST_NODE_TYPES.PropertyDefinition) && def.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
return def.key;
}
return this.getIdent(def.parent);
}
},
_a._nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/,
_a);
@@ -1,97 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-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><Subject>`',
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'
}
};
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 = (<TSESTree.Identifier>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 <verb> 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);
}
};
@@ -1,30 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
module.exports = new (_a = class ApiInterfaceNaming {
constructor() {
this.meta = {
messages: {
naming: 'Interfaces must not be prefixed with uppercase `I`',
}
};
}
create(context) {
return {
['TSInterfaceDeclaration Identifier']: (node) => {
const name = node.name;
if (ApiInterfaceNaming._nameRegExp.test(name)) {
context.report({
node,
messageId: 'naming'
});
}
}
};
}
},
_a._nameRegExp = /I[A-Z]/,
_a);
@@ -1,35 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-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`',
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSInterfaceDeclaration Identifier']: (node: any) => {
const name = (<TSESTree.Identifier>node).name;
if (ApiInterfaceNaming._nameRegExp.test(name)) {
context.report({
node,
messageId: 'naming'
});
}
}
};
}
};
@@ -1,25 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiLiteralOrTypes {
constructor() {
this.meta = {
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' },
messages: { useEnum: 'Use enums, not literal-or-types', }
};
}
create(context) {
return {
['TSTypeAnnotation TSUnionType']: (node) => {
if (node.types.every(value => value.type === 'TSLiteralType')) {
context.report({
node: node,
messageId: 'useEnum'
});
}
}
};
}
};
@@ -1,28 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-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', }
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSTypeAnnotation TSUnionType']: (node: any) => {
if ((<TSESTree.TSUnionType>node).types.every(value => value.type === 'TSLiteralType')) {
context.report({
node: node,
messageId: 'useEnum'
});
}
}
};
}
};
@@ -1,37 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
module.exports = new (_a = class ApiProviderNaming {
constructor() {
this.meta = {
messages: {
naming: 'A provider should only have functions like provideXYZ or resolveXYZ',
}
};
}
create(context) {
const config = context.options[0];
const allowed = new Set(config.allowed);
return {
['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node) => {
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'
});
}
}
};
}
},
_a._providerFunctionNames = /^(provide|resolve|prepare).+/,
_a);
@@ -1,45 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import { TSESTree } from '@typescript-eslint/experimental-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',
}
};
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 = (<TSESTree.TSInterfaceDeclaration>(<TSESTree.Identifier>node).parent?.parent).id.name;
if (allowed.has(interfaceName)) {
// allowed
return;
}
const methodName = (<any>(<TSESTree.TSMethodSignatureNonComputedName>node).key).name;
if (!ApiProviderNaming._providerFunctionNames.test(methodName)) {
context.report({
node,
messageId: 'naming'
});
}
}
};
}
};
@@ -1,35 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiEventNaming {
constructor() {
this.meta = {
messages: {
comment: 'region comments should start with a camel case identifier, `:`, then either a GH issue link or owner, e.g #region myProposalName: https://github.com/microsoft/vscode/issues/<number>',
}
};
}
create(context) {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node) => {
for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Line') {
continue;
}
if (!/^\s*#region /.test(comment.value)) {
continue;
}
if (!/^\s*#region ([a-z]+): (@[a-z]+|https:\/\/github.com\/microsoft\/vscode\/issues\/\d+)/i.test(comment.value)) {
context.report({
node: comment,
messageId: 'comment',
});
}
}
}
};
}
};
@@ -1,39 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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: {
comment: 'region comments should start with a camel case identifier, `:`, then either a GH issue link or owner, e.g #region myProposalName: https://github.com/microsoft/vscode/issues/<number>',
}
};
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 !== 'Line') {
continue;
}
if (!/^\s*#region /.test(comment.value)) {
continue;
}
if (!/^\s*#region ([a-z]+): (@[a-z]+|https:\/\/github.com\/microsoft\/vscode\/issues\/\d+)/i.test(comment.value)) {
context.report({
node: <any>comment,
messageId: 'comment',
});
}
}
}
};
}
};
@@ -1,24 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiEventNaming {
constructor() {
this.meta = {
messages: {
usage: 'Use the Thenable-type instead of the Promise type',
}
};
}
create(context) {
return {
['TSTypeAnnotation TSTypeReference Identifier[name="Promise"]']: (node) => {
context.report({
node,
messageId: 'usage',
});
}
};
}
};
@@ -1,30 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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',
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
return {
['TSTypeAnnotation TSTypeReference Identifier[name="Promise"]']: (node: any) => {
context.report({
node,
messageId: 'usage',
});
}
};
}
};
@@ -1,45 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiVsCodeInComments {
constructor() {
this.meta = {
messages: {
comment: `Don't use the term 'vs code' in comments`
}
};
}
create(context) {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node) => {
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;
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);
const end = sourceCode.getLocFromIndex(startIndex + match.index + match[0].length);
context.report({
messageId: 'comment',
loc: { start, end }
});
}
}
}
};
}
};
@@ -1,53 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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`
}
};
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 }
});
}
}
}
};
}
};
+19 -49
View File
File diff suppressed because one or more lines are too long
+19 -51
View File
@@ -9,8 +9,6 @@ import * as cp from 'child_process';
import * as glob from 'glob';
import * as gulp from 'gulp';
import * as path from 'path';
import * as through2 from 'through2'
import got from 'got';
import { Stream } from 'stream';
import * as File from 'vinyl';
import { createStatsStream } from './stats';
@@ -24,9 +22,13 @@ const buffer = require('gulp-buffer');
import * as jsoncParser from 'jsonc-parser';
import webpack = require('webpack');
import { getProductionDependencies } from './dependencies';
const util = require('./util');
import { getExtensionStream } from './builtInExtensions';
import { getVersion } from './getVersion';
import { remote, IOptions as IRemoteSrcOptions } from './gulpRemoteSource';
import { assetFromGithub } from './github';
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
const commit = getVersion(root);
const sourceMappingURLBase = `https://sqlopsbuilds.blob.core.windows.net/sourcemaps/${commit}`; // {{SQL CARBON EDIT}}
function minifyExtensionResources(input: Stream): Stream {
@@ -36,7 +38,7 @@ function minifyExtensionResources(input: Stream): Stream {
.pipe(buffer())
.pipe(es.mapSync((f: File) => {
const errors: jsoncParser.ParseError[] = [];
const value = jsoncParser.parse(f.contents.toString('utf8'), 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));
@@ -207,7 +209,6 @@ const baseHeaders = {
};
export function fromMarketplace(_serviceUrl: string, { name: extensionName, version, metadata }: IBuiltInExtension): Stream { // {{SQL CARBON EDIT}} We don't use the passed in service URL
const remote = require('gulp-remote-retry-src');
const json = require('gulp-json-editor') as typeof import('gulp-json-editor');
const [_publisher, name] = extensionName.split('.'); // {{SQL CARBON EDIT}} We don't have the publisher in our path
@@ -215,10 +216,9 @@ export function fromMarketplace(_serviceUrl: string, { name: extensionName, vers
fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...');
const options = {
const options: IRemoteSrcOptions = {
base: url,
requestOptions: {
gzip: true,
fetchOptions: {
headers: baseHeaders
}
};
@@ -235,39 +235,15 @@ export function fromMarketplace(_serviceUrl: string, { name: extensionName, vers
.pipe(packageJsonFilter.restore);
}
const ghApiHeaders: Record<string, string> = {
Accept: 'application/vnd.github.v3+json',
'User-Agent': userAgent,
};
if (process.env.GITHUB_TOKEN) {
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
}
const ghDownloadHeaders = {
...ghApiHeaders,
Accept: 'application/octet-stream',
};
export function fromGithub({ name, version, repo, metadata }: IBuiltInExtension): Stream {
const remote = require('gulp-remote-retry-src');
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 remote([`/repos${new URL(repo).pathname}/releases/tags/v${version}`], {
base: 'https://api.github.com',
requestOptions: { headers: ghApiHeaders }
}).pipe(through2.obj(function (file, _enc, callback) {
const asset = JSON.parse(file.contents.toString()).assets.find((a: any) => a.name.endsWith('.vsix'));
if (!asset) {
return callback(new Error(`Could not find vsix in release of ${repo} @ ${version}`));
}
const res = got.stream(asset.url, { headers: ghDownloadHeaders, followRedirect: true });
file.contents = res.pipe(through2());
callback(null, file);
}))
return assetFromGithub(new URL(repo).pathname, version, name => name.endsWith('.vsix'))
.pipe(buffer())
.pipe(vzip.src())
.pipe(filter('extension/**'))
@@ -285,7 +261,6 @@ const excludedExtensions = [
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
'vscode-custom-editor-tests',
'vscode-notebook-tests',
'integration-tests', // {{SQL CARBON EDIT}}
];
@@ -429,7 +404,7 @@ export function packageLocalExtensionsStream(forWeb: boolean): Stream {
);
}
export function packageMarketplaceExtensionsStream(forWeb: boolean, galleryServiceUrl?: string): Stream {
export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream {
const marketplaceExtensionsDescriptions = [
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
...(forWeb ? webBuiltInExtensions : [])
@@ -438,9 +413,8 @@ export function packageMarketplaceExtensionsStream(forWeb: boolean, galleryServi
es.merge(
...marketplaceExtensionsDescriptions
.map(extension => {
const input = (galleryServiceUrl ? fromMarketplace(galleryServiceUrl, extension) : fromGithub(extension))
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
return updateExtensionPackageJSON(input, (data: any) => {
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;
@@ -587,20 +561,14 @@ export async function webpackExtensions(taskName: string, isWatch: boolean, webp
for (const { configPath, outputRoot } of webpackConfigLocations) {
const configOrFnOrArray = require(configPath);
function addConfig(configOrFn: webpack.Configuration | Function) {
let config;
if (typeof configOrFn === 'function') {
config = (configOrFn as Function)({}, {});
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);
} else {
config = configOrFn;
}
if (outputRoot) {
config.output.path = path.join(outputRoot, path.relative(path.dirname(configPath), config.output.path));
}
webpackConfigs.push(configOrFn);
}
addConfig(configOrFnOrArray);
}
+17
View File
@@ -0,0 +1,17 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getVersion = void 0;
const git = 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;
}
exports.getVersion = getVersion;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0VmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImdldFZlcnNpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsNkJBQTZCO0FBRTdCLFNBQWdCLFVBQVUsQ0FBQyxJQUFZO0lBQ3RDLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUVqRCxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFO1FBQ3hELE9BQU8sR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQy9CO0lBRUQsT0FBTyxPQUFPLENBQUM7QUFDaEIsQ0FBQztBQVJELGdDQVFDIn0=
+16
View File
@@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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;
}
+1
View File
@@ -52,3 +52,4 @@ function getVersion(repo) {
return refs[ref];
}
exports.getVersion = getVersion;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZ2l0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7Z0dBR2dHO0FBQ2hHLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFFekI7O0dBRUc7QUFDSCxTQUFnQixVQUFVLENBQUMsSUFBWTtJQUN0QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNwQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN4QyxJQUFJLElBQVksQ0FBQztJQUVqQixJQUFJO1FBQ0gsSUFBSSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0tBQ2hEO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDWCxPQUFPLFNBQVMsQ0FBQztLQUNqQjtJQUVELElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ2pDLE9BQU8sSUFBSSxDQUFDO0tBQ1o7SUFFRCxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRTFDLElBQUksQ0FBQyxRQUFRLEVBQUU7UUFDZCxPQUFPLFNBQVMsQ0FBQztLQUNqQjtJQUVELE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUVwQyxJQUFJO1FBQ0gsT0FBTyxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztLQUMvQztJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1gsT0FBTztLQUNQO0lBRUQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDckQsSUFBSSxPQUFlLENBQUM7SUFFcEIsSUFBSTtRQUNILE9BQU8sR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztLQUN6RDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1gsT0FBTyxTQUFTLENBQUM7S0FDakI7SUFFRCxNQUFNLFNBQVMsR0FBRywyQkFBMkIsQ0FBQztJQUM5QyxJQUFJLFNBQWlDLENBQUM7SUFDdEMsTUFBTSxJQUFJLEdBQThCLEVBQUUsQ0FBQztJQUUzQyxPQUFPLFNBQVMsR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQzNDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDbEM7SUFFRCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNsQixDQUFDO0FBaERELGdDQWdEQyJ9
+48
View File
@@ -0,0 +1,48 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.assetFromGithub = void 0;
const node_fetch_1 = require("node-fetch");
const gulpRemoteSource_1 = require("./gulpRemoteSource");
const through2 = require("through2");
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 assetFromGithub(repo, version, assetFilter) {
return (0, gulpRemoteSource_1.remote)(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${version}`, {
base: 'https://api.github.com',
fetchOptions: { headers: ghApiHeaders }
}).pipe(through2.obj(async function (file, _enc, callback) {
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} @ ${version}`));
}
const response = await (0, node_fetch_1.default)(asset.url, { headers: ghDownloadHeaders });
if (response.ok) {
file.contents = response.body.pipe(through2());
callback(null, file);
}
else {
return callback(new Error(`Request ${response.url} failed with status code: ${response.status}`));
}
}));
}
exports.assetFromGithub = assetFromGithub;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l0aHViLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZ2l0aHViLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBR2hHLDJDQUErQjtBQUMvQix5REFBNEM7QUFDNUMscUNBQXFDO0FBRXJDLE1BQU0sWUFBWSxHQUEyQjtJQUM1QyxNQUFNLEVBQUUsZ0NBQWdDO0lBQ3hDLFlBQVksRUFBRSxjQUFjO0NBQzVCLENBQUM7QUFDRixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFO0lBQzdCLFlBQVksQ0FBQyxhQUFhLEdBQUcsUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7Q0FDakc7QUFDRCxNQUFNLGlCQUFpQixHQUFHO0lBQ3pCLEdBQUcsWUFBWTtJQUNmLE1BQU0sRUFBRSwwQkFBMEI7Q0FDbEMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLElBQVksRUFBRSxPQUFlLEVBQUUsV0FBc0M7SUFDcEcsT0FBTyxJQUFBLHlCQUFNLEVBQUMsVUFBVSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsbUJBQW1CLE9BQU8sRUFBRSxFQUFFO1FBQ2pGLElBQUksRUFBRSx3QkFBd0I7UUFDOUIsWUFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRTtLQUN2QyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxXQUFXLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUTtRQUN4RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBbUIsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzdHLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDWCxPQUFPLFFBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsSUFBSSxNQUFNLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztTQUN0RjtRQUNELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBQSxvQkFBSyxFQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLElBQUksUUFBUSxDQUFDLEVBQUUsRUFBRTtZQUNoQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDL0MsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztTQUNyQjthQUFNO1lBQ04sT0FBTyxRQUFRLENBQUMsSUFBSSxLQUFLLENBQUMsV0FBVyxRQUFRLENBQUMsR0FBRyw2QkFBNkIsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNsRztJQUVGLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBbEJELDBDQWtCQyJ9
+47
View File
@@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Stream } from 'stream';
import fetch from 'node-fetch';
import { remote } from './gulpRemoteSource';
import * as through2 from 'through2';
const ghApiHeaders: Record<string, string> = {
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
*/
export function assetFromGithub(repo: string, version: string, assetFilter: (name: string) => boolean): Stream {
return remote(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${version}`, {
base: 'https://api.github.com',
fetchOptions: { headers: ghApiHeaders }
}).pipe(through2.obj(async function (file, _enc, callback) {
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} @ ${version}`));
}
const response = await fetch(asset.url, { headers: ghDownloadHeaders });
if (response.ok) {
file.contents = response.body.pipe(through2());
callback(null, file);
} else {
return callback(new Error(`Request ${response.url} failed with status code: ${response.status}`));
}
}));
}
+71
View File
@@ -0,0 +1,71 @@
"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.remote = void 0;
const es = require("event-stream");
const node_fetch_1 = require("node-fetch");
const VinylFile = require("vinyl");
const through2 = require("through2");
const log = require("fancy-log");
const ansiColors = require("ansi-colors");
function remote(urls, options) {
if (options === undefined) {
options = {};
}
if (typeof options.base !== 'string' && options.base !== null) {
options.base = '/';
}
if (typeof options.buffer !== 'boolean') {
options.buffer = true;
}
if (!Array.isArray(urls)) {
urls = [urls];
}
return es.readArray(urls).pipe(es.map((data, cb) => {
const url = [options.base, data].join('');
fetchWithRetry(url, options).then(file => {
cb(undefined, file);
}, error => {
cb(error);
});
}));
}
exports.remote = remote;
async function fetchWithRetry(url, options, retries = 3, retryDelay = 250) {
try {
let startTime = 0;
if (options.verbose) {
log(`Start fetching ${ansiColors.magenta(url)}${retries !== 3 ? `(${3 - retries} retry}` : ''}`);
startTime = new Date().getTime();
}
const response = await (0, node_fetch_1.default)(url, options.fetchOptions);
if (options.verbose) {
log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`);
}
if (response.ok && (response.status >= 200 && response.status < 300)) {
// request must be piped out once created, or we'll get this error: "You cannot pipe after data has been emitted from the response."
const contents = options.buffer ? await response.buffer() : response.body.pipe(through2());
return new VinylFile({
cwd: '/',
base: options.base,
path: url,
contents
});
}
throw new Error(`Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`);
}
catch (e) {
if (retries > 0) {
await new Promise(c => setTimeout(c, retryDelay));
return fetchWithRetry(url, options, retries - 1, retryDelay * 3);
}
if (options.verbose) {
log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`);
}
throw e;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3VscFJlbW90ZVNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImd1bHBSZW1vdGVTb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsbUNBQW1DO0FBQ25DLDJDQUFnRDtBQUNoRCxtQ0FBbUM7QUFDbkMscUNBQXFDO0FBQ3JDLGlDQUFpQztBQUNqQywwQ0FBMEM7QUFTMUMsU0FBZ0IsTUFBTSxDQUFDLElBQXVCLEVBQUUsT0FBaUI7SUFDaEUsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFO1FBQzFCLE9BQU8sR0FBRyxFQUFFLENBQUM7S0FDYjtJQUVELElBQUksT0FBTyxPQUFPLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRTtRQUM5RCxPQUFPLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztLQUNuQjtJQUVELElBQUksT0FBTyxPQUFPLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtRQUN4QyxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztLQUN0QjtJQUVELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ3pCLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ2Q7SUFFRCxPQUFPLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQTJCLENBQUMsSUFBWSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BGLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUMsY0FBYyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDeEMsRUFBRSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMs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
+83
View File
@@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as es from 'event-stream';
import fetch, { RequestInit } from 'node-fetch';
import * as VinylFile from 'vinyl';
import * as through2 from 'through2';
import * as log from 'fancy-log';
import * as ansiColors from 'ansi-colors';
export interface IOptions {
base?: string;
buffer?: boolean;
fetchOptions?: RequestInit;
verbose?: boolean;
}
export function remote(urls: string[] | string, options: IOptions): es.ThroughStream {
if (options === undefined) {
options = {};
}
if (typeof options.base !== 'string' && options.base !== null) {
options.base = '/';
}
if (typeof options.buffer !== 'boolean') {
options.buffer = true;
}
if (!Array.isArray(urls)) {
urls = [urls];
}
return es.readArray(urls).pipe(es.map<string, VinylFile | void>((data: string, cb) => {
const url = [options.base, data].join('');
fetchWithRetry(url, options).then(file => {
cb(undefined, file);
}, error => {
cb(error);
});
}));
}
async function fetchWithRetry(url: string, options: IOptions, retries = 3, retryDelay = 250): Promise<VinylFile> {
try {
let startTime = 0;
if (options.verbose) {
log(`Start fetching ${ansiColors.magenta(url)}${retries !== 3 ? `(${3 - retries} retry}` : ''}`);
startTime = new Date().getTime();
}
const response = await fetch(url, options.fetchOptions);
if (options.verbose) {
log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`);
}
if (response.ok && (response.status >= 200 && response.status < 300)) {
// request must be piped out once created, or we'll get this error: "You cannot pipe after data has been emitted from the response."
const contents = options.buffer ? await response.buffer() : response.body.pipe(through2());
return new VinylFile({
cwd: '/',
base: options.base,
path: url,
contents
});
}
throw new Error(`Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`);
} catch (e) {
if (retries > 0) {
await new Promise(c => setTimeout(c, retryDelay));
return fetchWithRetry(url, options, retries - 1, retryDelay * 3);
}
if (options.verbose) {
log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`);
}
throw e;
}
}
+261 -481
View File
File diff suppressed because one or more lines are too long
+49 -5
View File
@@ -54,6 +54,10 @@
"name": "vs/workbench/contrib/codeActions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/commands",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/comments",
"project": "vscode-workbench"
@@ -90,6 +94,10 @@
"name": "vs/workbench/contrib/files",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/folding",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/html",
"project": "vscode-workbench"
@@ -110,6 +118,10 @@
"name": "vs/workbench/contrib/languageStatus",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/limitIndicator",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/keybindings",
"project": "vscode-workbench"
@@ -146,6 +158,14 @@
"name": "vs/workbench/contrib/notebook",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/interactiveEditor",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/chat",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/quickaccess",
"project": "vscode-workbench"
@@ -206,6 +226,10 @@
"name": "vs/workbench/contrib/terminal",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/terminalContrib",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/themes",
"project": "vscode-workbench"
@@ -254,10 +278,6 @@
"name": "vs/workbench/contrib/welcomeGettingStarted",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomeOverlay",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomePage",
"project": "vscode-workbench"
@@ -270,6 +290,10 @@
"name": "vs/workbench/contrib/welcomeWalkthrough",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/welcomeDialog",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/outline",
"project": "vscode-workbench"
@@ -303,7 +327,7 @@
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/offline",
"name": "vs/workbench/contrib/remoteTunnel",
"project": "vscode-workbench"
},
{
@@ -362,6 +386,10 @@
"name": "vs/workbench/services/history",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/hover",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/log",
"project": "vscode-workbench"
@@ -394,6 +422,10 @@
"name": "vs/workbench/services/search",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/suggest",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/textfile",
"project": "vscode-workbench"
@@ -477,6 +509,18 @@
{
"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"
}
]
}
+221 -474
View File
@@ -6,17 +6,16 @@
import * as path from 'path';
import * as fs from 'fs';
import { through, readable, ThroughStream } from 'event-stream';
import { map, merge, through, ThroughStream } from 'event-stream';
import * as jsonMerge from 'gulp-merge-json';
import * as File from 'vinyl';
import * as Is from 'is';
import * as xml2js from 'xml2js';
import * as https from 'https';
import * as gulp from 'gulp';
import * as fancyLog from 'fancy-log';
import * as ansiColors from 'ansi-colors';
import * as iconv from '@vscode/iconv-lite-umd';
const NUMBER_OF_CONCURRENT_DOWNLOADS = 4;
import { l10nJsonFormat, getL10nXlf, l10nJsonDetails, getL10nFilesFromXlf, getL10nJson } from '@vscode/l10n-dev';
function log(message: any, ...rest: any[]): void {
fancyLog(ansiColors.green('[i18n]'), message, ...rest);
@@ -51,18 +50,15 @@ export const extraLanguages: Language[] = [
{ id: 'tr', folderName: 'trk' }
];
// non built-in extensions also that are transifex and need to be part of the language packs
export const externalExtensionsWithTranslations = {
'vscode-chrome-debug': 'msjsdiag.debugger-for-chrome',
'vscode-node-debug': 'ms-vscode.node-debug',
'vscode-node-debug2': 'ms-vscode.node-debug2'
};
export interface Map<V> { // {{SQL CARBON EDIT}} Needed in locfunc.
export interface StringMap<V> { // {{SQL CARBON EDIT}} Needed in locfunc.
[key: string]: V;
}
export interface ParsedXLF { // {{SQL CARBON EDIT}} Needed in locfunc.
messages: StringMap<string>;
originalFilePath: string;
language: string;
}
interface Item {
id: string;
message: string;
@@ -74,12 +70,6 @@ export interface Resource {
project: string;
}
export interface ParsedXLF { // {{SQL CARBON EDIT}} Needed in locfunc.
messages: Map<string>;
originalFilePath: string;
language: string;
}
interface LocalizeInfo {
key: string;
comment: string[];
@@ -93,9 +83,9 @@ module LocalizeInfo {
}
interface BundledFormat {
keys: Map<(string | LocalizeInfo)[]>;
messages: Map<string[]>;
bundles: Map<string[]>;
keys: Record<string, (string | LocalizeInfo)[]>;
messages: Record<string, string[]>;
bundles: Record<string, string[]>;
}
module BundledFormat {
@@ -111,27 +101,6 @@ module BundledFormat {
}
}
interface ValueFormat {
message: string;
comment: string[];
}
interface PackageJsonFormat {
[key: string]: string | ValueFormat;
}
module PackageJsonFormat {
export function is(value: any): value is PackageJsonFormat {
if (Is.undef(value) || !Is.object(value)) {
return false;
}
return Object.keys(value).every(key => {
const element = value[key];
return Is.string(element) || (Is.object(element) && Is.defined(element.message) && Is.defined(element.comment));
});
}
}
interface BundledExtensionFormat {
[key: string]: {
messages: string[];
@@ -181,7 +150,7 @@ class TextModel {
export class XLF {
private buffer: string[];
private files: Map<Item[]>;
private files: Record<string, Item[]>;
public numberOfMessages: number;
constructor(public project: string) {
@@ -277,12 +246,12 @@ export class XLF {
static parsePseudo = function (xlfString: string): Promise<ParsedXLF[]> {
return new Promise((resolve) => {
const parser = new xml2js.Parser();
const files: { messages: Map<string>; originalFilePath: string; language: string }[] = [];
const files: { messages: StringMap<string>; originalFilePath: string; language: string }[] = [];
parser.parseString(xlfString, function (_err: any, result: any) {
const fileNodes: any[] = result['xliff']['file'];
fileNodes.forEach(file => {
const originalFilePath = file.$.original;
const messages: Map<string> = {};
const messages: StringMap<string> = {};
const transUnits = file.body[0]['trans-unit'];
if (transUnits) {
transUnits.forEach((unit: any) => {
@@ -300,11 +269,12 @@ export class XLF {
});
};
static parse = function (xlfString: string): Promise<ParsedXLF[]> {
static org_parse = function (xlfString: string): Promise<ParsedXLF[]> {
return new Promise((resolve, reject) => {
const parser = new xml2js.Parser();
const files: { messages: Map<string>; originalFilePath: string; language: string }[] = [];
const files: { messages: StringMap<string>; originalFilePath: string; language: string }[] = [];
parser.parseString(xlfString, function (err: any, result: any) {
if (err) {
@@ -325,7 +295,7 @@ export class XLF {
if (!language) {
reject(new Error(`XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.`));
}
const messages: Map<string> = {};
const messages: StringMap<string> = {};
const transUnits = file.body[0]['trans-unit'];
if (transUnits) {
@@ -354,49 +324,61 @@ export class XLF {
});
});
};
}
export interface ITask<T> {
(): T;
}
static parse = function (xlfString: string): Promise<l10nJsonDetails[]> {
return new Promise((resolve, reject) => {
const parser = new xml2js.Parser();
interface ILimitedTaskFactory<T> {
factory: ITask<Promise<T>>;
c: (value?: T | Promise<T>) => void;
e: (error?: any) => void;
}
const files: { messages: Record<string, string>; name: string; language: string }[] = [];
export class Limiter<T> {
private runningPromises: number;
private outstandingPromises: ILimitedTaskFactory<any>[];
parser.parseString(xlfString, function (err: any, result: any) {
if (err) {
reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`));
}
constructor(private maxDegreeOfParalellism: number) {
this.outstandingPromises = [];
this.runningPromises = 0;
}
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.`));
}
queue(factory: ITask<Promise<T>>): Promise<T> {
return new Promise<T>((c, e) => {
this.outstandingPromises.push({ factory, c, e });
this.consume();
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<string, string> = {};
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);
});
});
}
private consume(): void {
while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) {
const iLimitedTask = this.outstandingPromises.shift()!;
this.runningPromises++;
const promise = iLimitedTask.factory();
promise.then(iLimitedTask.c).catch(iLimitedTask.e);
promise.then(() => this.consumed()).catch(() => this.consumed());
}
}
private consumed(): void {
this.runningPromises--;
this.consume();
}
};
}
function sortLanguages(languages: Language[]): Language[] {
@@ -480,9 +462,9 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
const messageSection = json.messages;
const bundleSection = json.bundles;
const statistics: Map<number> = Object.create(null);
const statistics: Record<string, number> = Object.create(null);
const defaultMessages: Map<Map<string>> = Object.create(null);
const defaultMessages: Record<string, Record<string, string>> = Object.create(null);
const modules = Object.keys(keysSection);
modules.forEach((module) => {
const keys = keysSection[module];
@@ -491,7 +473,7 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
emitter.emit('error', `Message for module ${module} corrupted. Mismatch in number of keys and messages.`);
return;
}
const messageMap: Map<string> = Object.create(null);
const messageMap: Record<string, string> = Object.create(null);
defaultMessages[module] = messageMap;
keys.map((key, i) => {
if (typeof key === 'string') {
@@ -514,7 +496,7 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
}
statistics[language.id] = 0;
const localizedModules: Map<string[]> = Object.create(null);
const localizedModules: Record<string, string[]> = Object.create(null);
const languageFolderName = language.translationId || language.id;
const i18nFile = path.join(languageDirectory, `vscode-language-pack-${languageFolderName}`, 'translations', 'main.i18n.json');
let allMessages: I18nFormat | undefined;
@@ -611,7 +593,8 @@ export function processNlsFiles(opts: { fileHeader: string; languages: Language[
const editorProject: string = 'vscode-editor',
workbenchProject: string = 'vscode-workbench',
extensionsProject: string = 'vscode-extensions',
setupProject: string = 'vscode-setup';
setupProject: string = 'vscode-setup',
serverProject: string = 'vscode-server';
// {{SQL CARBON EDIT}}
const adsProject: string = 'ads-core';
@@ -629,6 +612,8 @@ export function getResource(sourceFile: string): Resource {
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 };
@@ -653,7 +638,7 @@ export function createXlfFilesForCoreBundle(): ThroughStream {
const basename = path.basename(file.path);
if (basename === 'nls.metadata.json') {
if (file.isBuffer()) {
const xlfs: Map<XLF> = Object.create(null);
const xlfs: Record<string, XLF> = Object.create(null);
const json: BundledFormat = JSON.parse((file.contents as Buffer).toString('utf8'));
// {{SQL CARBON EDIT}} - Must sort the keys for easier translation.
let sortedKeys = Object.keys(json.keys).sort();
@@ -698,6 +683,76 @@ export function createXlfFilesForCoreBundle(): ThroughStream {
});
}
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;
@@ -708,60 +763,62 @@ export function createXlfFilesForExtensions(): ThroughStream {
if (!stat.isDirectory()) {
return;
}
const extensionName = path.basename(extensionFolder.path);
if (extensionName === 'node_modules') {
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 _xlf: XLF;
function getXlf() {
if (!_xlf) {
_xlf = new XLF(extensionsProject);
let _l10nMap: Map<string, l10nJsonFormat>;
function getL10nMap() {
if (!_l10nMap) {
_l10nMap = new Map();
}
return _xlf;
return _l10nMap;
}
gulp.src([`.build/extensions/${extensionName}/package.nls.json`, `.build/extensions/${extensionName}/**/nls.metadata.json`], { allowEmpty: true }).pipe(through(function (file: File) {
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: PackageJsonFormat = JSON.parse(buffer.toString('utf8'));
const keys: Array<string | LocalizeInfo> = [];
const messages: string[] = [];
Object.keys(json).forEach((key) => {
const value = json[key];
if (Is.string(value)) {
keys.push(key);
messages.push(value);
} else if (value) {
keys.push({
key,
comment: value.comment
});
messages.push(value.message);
} else {
keys.push(key);
messages.push(`Unknown message for key: ${key}`);
}
});
getXlf().addFile(`extensions/${extensionName}/package`, keys, messages);
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/${extensionName}`, path.dirname(file.path));
const relPath = path.relative(`.build/extensions/${extensionFolderName}`, path.dirname(file.path));
for (const file in json) {
const fileContent = json[file];
getXlf().addFile(`extensions/${extensionName}/${relPath}/${file}`, fileContent.keys, fileContent.messages);
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 (_xlf) {
if (_l10nMap?.size > 0) {
const xlfFile = new File({
path: path.join(extensionsProject, extensionName + '.xlf'),
contents: Buffer.from(_xlf.toString(), 'utf8')
path: path.join(extensionsProject, extensionId + '.xlf'),
contents: Buffer.from(getL10nXlf(_l10nMap), 'utf8')
});
folderStream.queue(xlfFile);
}
@@ -837,322 +894,8 @@ export function createXlfFilesForIsl(): ThroughStream {
});
}
export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream {
const tryGetPromises: Array<Promise<boolean>> = [];
const updateCreatePromises: Array<Promise<boolean>> = [];
return through(function (this: ThroughStream, file: File) {
const project = path.dirname(file.relative);
const fileName = path.basename(file.path);
const slug = fileName.substr(0, fileName.length - '.xlf'.length);
const credentials = `${username}:${password}`;
// Check if resource already exists, if not, then create it.
let promise = tryGetResource(project, slug, apiHostname, credentials);
tryGetPromises.push(promise);
promise.then(exists => {
if (exists) {
promise = updateResource(project, slug, file, apiHostname, credentials);
} else {
promise = createResource(project, slug, file, apiHostname, credentials);
}
updateCreatePromises.push(promise);
});
}, function () {
// End the pipe only after all the communication with Transifex API happened
Promise.all(tryGetPromises).then(() => {
Promise.all(updateCreatePromises).then(() => {
this.queue(null);
}).catch((reason) => { throw new Error(reason); });
}).catch((reason) => { throw new Error(reason); });
});
}
function getAllResources(project: string, apiHostname: string, username: string, password: string): Promise<string[]> {
return new Promise((resolve, reject) => {
const credentials = `${username}:${password}`;
const options = {
hostname: apiHostname,
path: `/api/2/project/${project}/resources`,
auth: credentials,
method: 'GET'
};
const request = https.request(options, (res) => {
const buffer: Buffer[] = [];
res.on('data', (chunk: Buffer) => buffer.push(chunk));
res.on('end', () => {
if (res.statusCode === 200) {
const json = JSON.parse(Buffer.concat(buffer).toString());
if (Array.isArray(json)) {
resolve(json.map(o => o.slug));
return;
}
reject(`Unexpected data format. Response code: ${res.statusCode}.`);
} else {
reject(`No resources in ${project} returned no data. Response code: ${res.statusCode}.`);
}
});
});
request.on('error', (err) => {
reject(`Failed to query resources in ${project} with the following error: ${err}. ${options.path}`);
});
request.end();
});
}
export function findObsoleteResources(apiHostname: string, username: string, password: string): ThroughStream {
const resourcesByProject: Map<string[]> = Object.create(null);
resourcesByProject[extensionsProject] = ([] as any[]).concat(externalExtensionsWithTranslations); // clone
return through(function (this: ThroughStream, file: File) {
const project = path.dirname(file.relative);
const fileName = path.basename(file.path);
const slug = fileName.substr(0, fileName.length - '.xlf'.length);
let slugs = resourcesByProject[project];
if (!slugs) {
resourcesByProject[project] = slugs = [];
}
slugs.push(slug);
this.push(file);
}, function () {
const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'));
const i18Resources = [...json.editor, ...json.workbench].map((r: Resource) => r.project + '/' + r.name.replace(/\//g, '_'));
const extractedResources: string[] = [];
for (const project of [workbenchProject, editorProject]) {
for (const resource of resourcesByProject[project]) {
if (resource !== 'setup_messages') {
extractedResources.push(project + '/' + resource);
}
}
}
if (i18Resources.length !== extractedResources.length) {
console.log(`[i18n] Obsolete resources in file 'build/lib/i18n.resources.json': JSON.stringify(${i18Resources.filter(p => extractedResources.indexOf(p) === -1)})`);
console.log(`[i18n] Missing resources in file 'build/lib/i18n.resources.json': JSON.stringify(${extractedResources.filter(p => i18Resources.indexOf(p) === -1)})`);
}
const promises: Array<Promise<void>> = [];
for (const project in resourcesByProject) {
promises.push(
getAllResources(project, apiHostname, username, password).then(resources => {
const expectedResources = resourcesByProject[project];
const unusedResources = resources.filter(resource => resource && expectedResources.indexOf(resource) === -1);
if (unusedResources.length) {
console.log(`[transifex] Obsolete resources in project '${project}': ${unusedResources.join(', ')}`);
}
})
);
}
return Promise.all(promises).then(_ => {
this.push(null);
}).catch((reason) => { throw new Error(reason); });
});
}
function tryGetResource(project: string, slug: string, apiHostname: string, credentials: string): Promise<boolean> {
return new Promise((resolve, reject) => {
const options = {
hostname: apiHostname,
path: `/api/2/project/${project}/resource/${slug}/?details`,
auth: credentials,
method: 'GET'
};
const request = https.request(options, (response) => {
if (response.statusCode === 404) {
resolve(false);
} else if (response.statusCode === 200) {
resolve(true);
} else {
reject(`Failed to query resource ${project}/${slug}. Response: ${response.statusCode} ${response.statusMessage}`);
}
});
request.on('error', (err) => {
reject(`Failed to get ${project}/${slug} on Transifex: ${err}`);
});
request.end();
});
}
function createResource(project: string, slug: string, xlfFile: File, apiHostname: string, credentials: any): Promise<any> {
return new Promise((_resolve, reject) => {
const data = JSON.stringify({
'content': xlfFile.contents.toString(),
'name': slug,
'slug': slug,
'i18n_type': 'XLIFF'
});
const options = {
hostname: apiHostname,
path: `/api/2/project/${project}/resources`,
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data)
},
auth: credentials,
method: 'POST'
};
const request = https.request(options, (res) => {
if (res.statusCode === 201) {
log(`Resource ${project}/${slug} successfully created on Transifex.`);
} else {
reject(`Something went wrong in the request creating ${slug} in ${project}. ${res.statusCode}`);
}
});
request.on('error', (err) => {
reject(`Failed to create ${project}/${slug} on Transifex: ${err}`);
});
request.write(data);
request.end();
});
}
/**
* The following link provides information about how Transifex handles updates of a resource file:
* https://dev.befoolish.co/tx-docs/public/projects/updating-content#what-happens-when-you-update-files
*/
function updateResource(project: string, slug: string, xlfFile: File, apiHostname: string, credentials: string): Promise<any> {
return new Promise<void>((resolve, reject) => {
const data = JSON.stringify({ content: xlfFile.contents.toString() });
const options = {
hostname: apiHostname,
path: `/api/2/project/${project}/resource/${slug}/content`,
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data)
},
auth: credentials,
method: 'PUT'
};
const request = https.request(options, (res) => {
if (res.statusCode === 200) {
res.setEncoding('utf8');
let responseBuffer: string = '';
res.on('data', function (chunk) {
responseBuffer += chunk;
});
res.on('end', () => {
const response = JSON.parse(responseBuffer);
log(`Resource ${project}/${slug} successfully updated on Transifex. Strings added: ${response.strings_added}, updated: ${response.strings_added}, deleted: ${response.strings_added}`);
resolve();
});
} else {
reject(`Something went wrong in the request updating ${slug} in ${project}. ${res.statusCode}`);
}
});
request.on('error', (err) => {
reject(`Failed to update ${project}/${slug} on Transifex: ${err}`);
});
request.write(data);
request.end();
});
}
export function pullSetupXlfFiles(apiHostname: string, username: string, password: string, language: Language, includeDefault: boolean): NodeJS.ReadableStream {
const setupResources = [{ name: 'setup_messages', project: workbenchProject }];
if (includeDefault) {
setupResources.push({ name: 'setup_default', project: setupProject });
}
return pullXlfFiles(apiHostname, username, password, language, setupResources);
}
function pullXlfFiles(apiHostname: string, username: string, password: string, language: Language, resources: Resource[]): NodeJS.ReadableStream {
const credentials = `${username}:${password}`;
const expectedTranslationsCount = resources.length;
let translationsRetrieved = 0, called = false;
return readable(function (_count: any, callback: any) {
// Mark end of stream when all resources were retrieved
if (translationsRetrieved === expectedTranslationsCount) {
return this.emit('end');
}
if (!called) {
called = true;
const stream = this;
resources.map(function (resource) {
retrieveResource(language, resource, apiHostname, credentials).then((file: File | null) => {
if (file) {
stream.emit('data', file);
}
translationsRetrieved++;
}).catch(error => { throw new Error(error); });
});
}
callback();
});
}
const limiter = new Limiter<File | null>(NUMBER_OF_CONCURRENT_DOWNLOADS);
function retrieveResource(language: Language, resource: Resource, apiHostname: string, credentials: string): Promise<File | null> {
return limiter.queue(() => new Promise<File | null>((resolve, reject) => {
const slug = resource.name.replace(/\//g, '_');
const project = resource.project;
const transifexLanguageId = language.id === 'ps' ? 'en' : language.translationId || language.id;
const options = {
hostname: apiHostname,
path: `/api/2/project/${project}/resource/${slug}/translation/${transifexLanguageId}?file&mode=onlyreviewed`,
auth: credentials,
port: 443,
method: 'GET'
};
console.log('[transifex] Fetching ' + options.path);
const request = https.request(options, (res) => {
const xlfBuffer: Buffer[] = [];
res.on('data', (chunk: Buffer) => xlfBuffer.push(chunk));
res.on('end', () => {
if (res.statusCode === 200) {
resolve(new File({ contents: Buffer.concat(xlfBuffer), path: `${project}/${slug}.xlf` }));
} else if (res.statusCode === 404) {
console.log(`[transifex] ${slug} in ${project} returned no data.`);
resolve(null);
} else {
reject(`${slug} in ${project} returned no data. Response code: ${res.statusCode}.`);
}
});
});
request.on('error', (err) => {
reject(`Failed to query resource ${slug} with the following error: ${err}. ${options.path}`);
});
request.end();
}));
}
export function prepareI18nFiles(): ThroughStream {
const parsePromises: Promise<ParsedXLF[]>[] = [];
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 = createI18nFile(file.originalFilePath, file.messages);
stream.queue(translatedFile);
});
}
);
}, function () {
Promise.all(parsePromises)
.then(() => { this.queue(null); })
.catch(reason => { throw new Error(reason); });
});
}
export function createI18nFile(originalFilePath: string, messages: any): File { // {{SQL CARBON EDIT}} Needed for locfunc.
let result = Object.create(null);
export function createI18nFile(name: string, messages: any): File { // {{SQL CARBON EDIT}} Needed for locfunc.
const result = Object.create(null);
result[''] = [
'--------------------------------------------------------------------------------------------',
'Copyright (c) Microsoft Corporation. All rights reserved.',
@@ -1169,7 +912,7 @@ export function createI18nFile(originalFilePath: string, messages: any): File {
content = content.replace(/\n/g, '\r\n');
}
return new File({
path: path.join(originalFilePath + '.i18n.json'),
path: path.join(name + '.i18n.json'),
contents: Buffer.from(content, 'utf8')
});
}
@@ -1177,7 +920,7 @@ export function createI18nFile(originalFilePath: string, messages: any): File {
export interface I18nPack { // {{SQL CARBON EDIT}} Needed in locfunc.
version: string;
contents: {
[path: string]: Map<string>;
[path: string]: Record<string, string>;
};
}
@@ -1188,38 +931,48 @@ export interface TranslationPath {
resourceName: string;
}
export function prepareI18nPackFiles(externalExtensions: Map<string>, resultingTranslationPaths: TranslationPath[], pseudo = false): NodeJS.ReadWriteStream {
const parsePromises: Promise<ParsedXLF[]>[] = [];
function getRecordFromL10nJsonFormat(l10nJsonFormat: l10nJsonFormat): Record<string, string> {
const record: Record<string, string> = {};
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<l10nJsonDetails[]>[] = [];
const mainPack: I18nPack = { version: i18nPackVersion, contents: {} };
const extensionsPacks: Map<I18nPack> = {};
const extensionsPacks: Record<string, I18nPack> = {};
const errors: any[] = [];
return through(function (this: ThroughStream, xlf: File) {
const project = path.basename(path.dirname(path.dirname(xlf.relative)));
const resource = path.basename(xlf.relative, '.xlf');
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 = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents);
const parsePromise = getL10nFilesFromXlf(contents);
parsePromises.push(parsePromise);
parsePromise.then(
resolvedFiles => {
resolvedFiles.forEach(file => {
const path = file.originalFilePath;
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: {} };
}
const externalId = externalExtensions[resource];
if (!externalId) { // internal extension: remove 'extensions/extensionId/' segnent
const secondSlash = path.indexOf('/', firstSlash + 1);
extPack.contents[path.substr(secondSlash + 1)] = file.messages;
} else {
extPack.contents[path] = file.messages;
}
// remove 'extensions/extensionId/' segment
const secondSlash = path.indexOf('/', firstSlash + 1);
extPack.contents[path.substring(secondSlash + 1)] = getRecordFromL10nJsonFormat(file.messages);
} else {
mainPack.contents[path.substr(firstSlash + 1)] = file.messages;
mainPack.contents[path.substring(firstSlash + 1)] = getRecordFromL10nJsonFormat(file.messages);
}
});
}
@@ -1236,17 +989,11 @@ export function prepareI18nPackFiles(externalExtensions: Map<string>, resultingT
resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' });
this.queue(translatedMainFile);
for (const extension in extensionsPacks) {
const translatedExtFile = createI18nFile(`extensions/${extension}`, extensionsPacks[extension]);
for (const extensionId in extensionsPacks) {
const translatedExtFile = createI18nFile(`extensions/${extensionId}`, extensionsPacks[extensionId]);
this.queue(translatedExtFile);
const externalExtensionId = externalExtensions[extension];
if (externalExtensionId) {
resultingTranslationPaths.push({ id: externalExtensionId, resourceName: `extensions/${extension}.i18n.json` });
} else {
resultingTranslationPaths.push({ id: `vscode.${extension}`, resourceName: `extensions/${extension}.i18n.json` });
}
resultingTranslationPaths.push({ id: extensionId, resourceName: `extensions/${extensionId}.i18n.json` });
}
this.queue(null);
})
@@ -1257,7 +1004,7 @@ export function prepareI18nPackFiles(externalExtensions: Map<string>, resultingT
}
export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup): ThroughStream {
const parsePromises: Promise<ParsedXLF[]>[] = [];
const parsePromises: Promise<l10nJsonDetails[]>[] = [];
return through(function (this: ThroughStream, xlf: File) {
const stream = this;
@@ -1266,7 +1013,7 @@ export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup):
parsePromise.then(
resolvedFiles => {
resolvedFiles.forEach(file => {
const translatedFile = createIslFile(file.originalFilePath, file.messages, language, innoSetupConfig);
const translatedFile = createIslFile(file.name, file.messages, language, innoSetupConfig);
stream.queue(translatedFile);
});
}
@@ -1282,13 +1029,13 @@ export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup):
});
}
function createIslFile(originalFilePath: string, messages: Map<string>, language: Language, innoSetup: InnoSetup): File {
function createIslFile(name: string, messages: l10nJsonFormat, language: Language, innoSetup: InnoSetup): File {
const content: string[] = [];
let originalContent: TextModel;
if (path.basename(originalFilePath) === 'Default') {
originalContent = new TextModel(fs.readFileSync(originalFilePath + '.isl', 'utf8'));
if (path.basename(name) === 'Default') {
originalContent = new TextModel(fs.readFileSync(name + '.isl', 'utf8'));
} else {
originalContent = new TextModel(fs.readFileSync(originalFilePath + '.en.isl', 'utf8'));
originalContent = new TextModel(fs.readFileSync(name + '.en.isl', 'utf8'));
}
originalContent.lines.forEach(line => {
if (line.length > 0) {
@@ -1311,7 +1058,7 @@ function createIslFile(originalFilePath: string, messages: Map<string>, language
}
});
const basename = path.basename(originalFilePath);
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);
File diff suppressed because one or more lines are too long
+8 -4
View File
@@ -52,11 +52,13 @@ const CORE_TYPES = [
'BigInt64Array',
'btoa',
'atob',
'AbortController',
'AbortSignal',
'MessageChannel',
'MessagePort',
'URL',
'URLSearchParams'
'URLSearchParams',
'ReadonlyArray',
];
// Types that are defined in a common layer but are known to be only
@@ -66,7 +68,9 @@ const NATIVE_TYPES = [
'INativeEnvironmentService',
'AbstractNativeEnvironmentService',
'INativeWindowConfiguration',
'ICommonNativeHostService'
'ICommonNativeHostService',
'INativeHostService',
'IMainProcessService'
];
const RULES: IRule[] = [
@@ -268,7 +272,7 @@ function checkFile(program: ts.Program, sourceFile: ts.SourceFile, rule: IRule)
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})`);
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;
@@ -295,7 +299,7 @@ function checkFile(program: ts.Program, sourceFile: ts.SourceFile, rule: IRule)
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})`);
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;
+2 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -111,13 +111,13 @@ function updateMainI18nFile(existingTranslationFilePath: string, originalFilePat
export function modifyI18nPackFiles(existingTranslationFolder: string, resultingTranslationPaths: i18n.TranslationPath[], pseudo = false): NodeJS.ReadWriteStream {
let parsePromises: Promise<i18n.ParsedXLF[]>[] = [];
let mainPack: i18n.I18nPack = { version: i18n.i18nPackVersion, contents: {} };
let extensionsPacks: i18n.Map<i18n.I18nPack> = {};
let extensionsPacks: i18n.StringMap<i18n.I18nPack> = {};
let errors: any[] = [];
return es.through(function (this: es.ThroughStream, xlf: File) {
let rawResource = path.basename(xlf.relative, '.xlf');
let resource = rawResource.substring(0, rawResource.lastIndexOf('.'));
let contents = xlf.contents.toString();
let parsePromise = pseudo ? i18n.XLF.parsePseudo(contents) : i18n.XLF.parse(contents);
let parsePromise = pseudo ? i18n.XLF.parsePseudo(contents) : i18n.XLF.org_parse(contents);
parsePromises.push(parsePromise);
parsePromise.then(
resolvedFiles => {
File diff suppressed because one or more lines are too long
+604
View File
@@ -0,0 +1,604 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as ts from 'typescript';
import * as path from 'path';
// import * as fs from 'fs'; // {{SQL CARBON EDIT}} - disable unused
// import { argv } from 'process';
import { Mapping, SourceMapGenerator } from 'source-map';
import { pathToFileURL } from 'url';
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 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
private _value = 0;
private readonly _isNameTaken: (name: string) => boolean;
constructor(isNameTaken: (name: string) => boolean) {
this._isNameTaken = name => ShortIdent._keywords.has(name) || isNameTaken(name);
}
next(): string {
const candidate = ShortIdent.convert(this._value);
this._value++;
if (this._isNameTaken(candidate)) {
// try again
return this.next();
}
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<string, { type: FieldType; pos: number }>();
private replacements: Map<string, string> | 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 identPool = new ShortIdent(name => {
// 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;
});
for (const [name, info] of data.fields) {
if (ClassData._shouldMangle(info.type)) {
const shortName = identPool.next();
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 ((<any>this.node.getSourceFile()).identifiers instanceof Map) {
// taken by any other usage
if ((<any>this.node.getSourceFile()).identifiers.has(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;
}
}
class StaticLanguageServiceHost implements ts.LanguageServiceHost {
private readonly _cmdLine: ts.ParsedCommandLine;
private readonly _scriptSnapshots: Map<string, ts.IScriptSnapshot> = new Map();
constructor(readonly projectPath: string) {
const existingOptions: Partial<ts.CompilerOptions> = {};
const parsed = ts.readConfigFile(projectPath, ts.sys.readFile);
if (parsed.error) {
throw parsed.error;
}
this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions);
if (this._cmdLine.errors.length > 0) {
throw parsed.error;
}
}
getCompilationSettings(): ts.CompilerOptions {
return this._cmdLine.options;
}
getScriptFileNames(): string[] {
return this._cmdLine.fileNames;
}
getScriptVersion(_fileName: string): string {
return '1';
}
getProjectVersion(): string {
return '1';
}
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
let result: ts.IScriptSnapshot | undefined = this._scriptSnapshots.get(fileName);
if (result === undefined) {
const content = ts.sys.readFile(fileName);
if (content === undefined) {
return undefined;
}
result = ts.ScriptSnapshot.fromString(content);
this._scriptSnapshots.set(fileName, result);
}
return result;
}
getCurrentDirectory(): string {
return path.dirname(this.projectPath);
}
getDefaultLibFileName(options: ts.CompilerOptions): string {
return ts.getDefaultLibFilePath(options);
}
directoryExists = ts.sys.directoryExists;
getDirectories = ts.sys.getDirectories;
fileExists = ts.sys.fileExists;
readFile = ts.sys.readFile;
readDirectory = ts.sys.readDirectory;
// this is necessary to make source references work.
realpath = ts.sys.realpath;
}
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<string, ClassData>();
private readonly service: ts.LanguageService;
constructor(readonly projectPath: string, readonly log: typeof console.log = () => { }) {
this.service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
}
computeNewFileContents(strictImplicitPublicHandling?: Set<string>): Map<string, MangleOutput> {
// STEP: find all classes and their field info
const visit = (node: ts.Node): void => {
if (ts.isClassDeclaration(node) || ts.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));
}
ts.forEachChild(node, visit);
};
for (const file of this.service.getProgram()!.getSourceFiles()) {
if (!file.isDeclarationFile) {
ts.forEachChild(file, visit);
}
}
this.log(`Done collecting classes: ${this.allClassDataByKey.size}`);
// STEP: connect sub and super-types
const setupParents = (data: ClassData) => {
const extendsClause = data.node.heritageClauses?.find(h => h.token === ts.SyntaxKind.ExtendsKeyword);
if (!extendsClause) {
// no EXTENDS-clause
return;
}
const info = this.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<string, string[]>();
let violationsCauseFailure = false;
for (const data of this.allClassDataByKey.values()) {
ClassData.makeImplicitPublicActuallyPublic(data, (name: string, 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 replacements`);
// STEP: prepare rename edits
type Edit = { newText: string; offset: number; length: number };
const editsByFile = new Map<string, Edit[]>();
const appendEdit = (fileName: string, edit: Edit) => {
const edits = editsByFile.get(fileName);
if (!edits) {
editsByFile.set(fileName, [edit]);
} else {
edits.push(edit);
}
};
for (const data of this.allClassDataByKey.values()) {
if (hasModifier(data.node, ts.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 === FieldType.Public) {
continue fields;
}
parent = parent.parent;
}
const newText = data.lookupShortName(name);
const locations = this.service.findRenameLocations(data.fileName, info.pos, false, false, true) ?? [];
for (const loc of locations) {
appendEdit(loc.fileName, {
newText: (loc.prefixText || '') + newText + (loc.suffixText || ''),
offset: loc.textSpan.start,
length: loc.textSpan.length
});
}
}
}
this.log(`Done preparing edits: ${editsByFile.size} files`);
// STEP: apply all rename edits (per file)
const result = new Map<string, MangleOutput>();
let savedBytes = 0;
for (const item of this.service.getProgram()!.getSourceFiles()) {
const { mapRoot, sourceRoot } = this.service.getProgram()!.getCompilerOptions();
const projectDir = path.dirname(this.projectPath);
const sourceMapRoot = mapRoot ?? pathToFileURL(sourceRoot ?? projectDir).toString();
// source maps
let generator: SourceMapGenerator | undefined;
let newFullText: string;
const edits = editsByFile.get(item.fileName);
if (!edits) {
// just copy
newFullText = item.getFullText();
} else {
// source map generator
const relativeFileName = normalize(path.relative(projectDir, item.fileName));
const mappingsByLine = new Map<number, Mapping[]>();
// apply renames
edits.sort((a, b) => b.offset - a.offset);
const characters = item.getFullText().split('');
let lastEdit: Edit | undefined;
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 SourceMapGenerator({ file: path.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() });
}
this.log(`Done: ${savedBytes / 1000}kb saved`);
return result;
}
}
// --- ast utils
function hasModifier(node: ts.Node, kind: ts.SyntaxKind) {
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
return Boolean(modifiers?.find(mode => mode.kind === kind));
}
function normalize(path: string): string {
return path.replace(/\\/g, '/');
}
// async function _run() {
// const projectPath = path.join(__dirname, '../../src/tsconfig.json');
// const projectBase = path.dirname(projectPath);
// const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2');
// for await (const [fileName, contents] of new Mangler(projectPath, console.log).computeNewFileContents(new Set(['saveState']))) {
// const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName));
// await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true });
// await fs.promises.writeFile(newFilePath, contents.out);
// if (contents.sourceMap) {
// await fs.promises.writeFile(newFilePath + '.map', contents.sourceMap);
// }
// }
// }
// if (__filename === argv[1]) {
// _run();
// }
File diff suppressed because one or more lines are too long
+5 -2
View File
@@ -115,7 +115,7 @@ function getNodeText(sourceFile: ts.SourceFile, node: { pos: number; end: number
return sourceFile.getFullText().substring(node.pos, node.end);
}
function hasModifier(modifiers: ts.NodeArray<ts.ModifierLike> | undefined, kind: ts.SyntaxKind): boolean {
function hasModifier(modifiers: readonly ts.ModifierLike[] | undefined, kind: ts.SyntaxKind): boolean {
if (modifiers) {
for (let i = 0; i < modifiers.length; i++) {
const mod = modifiers[i];
@@ -128,7 +128,10 @@ function hasModifier(modifiers: ts.NodeArray<ts.ModifierLike> | undefined, kind:
}
function isStatic(ts: typeof import('typescript'), member: ts.ClassElement | ts.TypeElement): boolean {
return hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword);
if (ts.canHaveModifiers(member)) {
return hasModifier(ts.getModifiers(member), ts.SyntaxKind.StaticKeyword);
}
return false;
}
function isDefaultExport(ts: typeof import('typescript'), declaration: ts.InterfaceDeclaration | ts.ClassDeclaration): boolean {
+13 -6
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -15,3 +15,4 @@ const arch = process.arch;
const node = platform === 'win32' ? 'node.exe' : 'node';
const nodePath = path.join(root, '.build', 'node', `v${version}`, `${platform}-${arch}`, node);
console.log(nodePath);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm5vZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOztBQUVoRyw2QkFBNkI7QUFDN0IseUJBQXlCO0FBRXpCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQ25ELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUN4RCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUNuRCxNQUFNLE9BQU8sR0FBRyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFekQsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztBQUNsQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO0FBRTFCLE1BQU0sSUFBSSxHQUFHLFFBQVEsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0FBQ3hELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxPQUFPLEVBQUUsRUFBRSxHQUFHLFFBQVEsSUFBSSxJQUFJLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUUvRixPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDIn0=
+104 -47
View File
File diff suppressed because one or more lines are too long
+171 -59
View File
@@ -56,7 +56,7 @@ function loaderPlugin(src: string, base: string, amdModuleId: string | undefined
);
}
function loader(src: string, bundledFileHeader: string, bundleLoader: boolean, externalLoaderInfo?: any): NodeJS.ReadWriteStream {
function loader(src: string, bundledFileHeader: string, bundleLoader: boolean, externalLoaderInfo?: util.IExternalLoaderInfo): NodeJS.ReadWriteStream {
let loaderStream = gulp.src(`${src}/vs/loader.js`, { base: `${src}` });
if (bundleLoader) {
loaderStream = es.merge(
@@ -97,7 +97,7 @@ function loader(src: string, bundledFileHeader: string, bundleLoader: boolean, e
files.push(new VinylFile({
path: 'fake2',
base: '.',
contents: Buffer.from(`require.config(${JSON.stringify(externalLoaderInfo, undefined, 2)});`)
contents: Buffer.from(emitExternalLoaderInfo(externalLoaderInfo))
}));
}
for (const file of files) {
@@ -109,6 +109,19 @@ function loader(src: string, bundledFileHeader: string, bundleLoader: boolean, e
);
}
function emitExternalLoaderInfo(externalLoaderInfo: util.IExternalLoaderInfo): string {
const externalBaseUrl = externalLoaderInfo.baseUrl;
externalLoaderInfo.baseUrl = '$BASE_URL';
// If defined, use the runtime configured baseUrl.
const code = `
(function() {
const baseUrl = require.getConfig().baseUrl || ${JSON.stringify(externalBaseUrl)};
require.config(${JSON.stringify(externalLoaderInfo, undefined, 2)});
})();`;
return code.replace('"$BASE_URL"', 'baseUrl');
}
function toConcatStream(src: string, bundledFileHeader: string, sources: bundle.IFile[], dest: string, fileContentMapper: (contents: string, path: string) => string): NodeJS.ReadWriteStream {
const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);
@@ -155,7 +168,7 @@ function toBundleStream(src: string, bundledFileHeader: string, bundles: bundle.
}));
}
export interface IOptimizeTaskOpts {
export interface IOptimizeAMDTaskOpts {
/**
* The folder to read files from.
*/
@@ -172,7 +185,7 @@ export interface IOptimizeTaskOpts {
/**
* Additional info we append to the end of the loader
*/
externalLoaderInfo?: any;
externalLoaderInfo?: util.IExternalLoaderInfo;
/**
* (true by default - append css and nls to loader)
*/
@@ -186,16 +199,12 @@ export interface IOptimizeTaskOpts {
*/
bundleInfo: boolean;
/**
* (out folder name)
*/
out: string;
/**
* (out folder name)
* Language configuration.
*/
languages?: Language[];
/**
* File contents interceptor
* @param contents The contens of the file
* @param contents The contents of the file
* @param path The absolute file path, always using `/`, even on Windows
*/
fileContentMapper?: (contents: string, path: string) => string;
@@ -207,67 +216,164 @@ const DEFAULT_FILE_HEADER = [
' *--------------------------------------------------------*/'
].join('\n');
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
function optimizeAMDTask(opts: IOptimizeAMDTaskOpts): NodeJS.ReadWriteStream {
const src = opts.src;
const entryPoints = opts.entryPoints;
const resources = opts.resources;
const loaderConfig = opts.loaderConfig;
const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
const out = opts.out;
const fileContentMapper = opts.fileContentMapper || ((contents: string, _path: string) => contents);
return function () {
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
const bundlesStream = es.through(); // this stream will contain the bundled files
const resourcesStream = es.through(); // this stream will contain the resources
const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
const bundlesStream = es.through(); // this stream will contain the bundled files
const resourcesStream = es.through(); // this stream will contain the resources
const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
bundle.bundle(entryPoints, loaderConfig, function (err, result) {
if (err || !result) { return bundlesStream.emit('error', JSON.stringify(err)); }
bundle.bundle(entryPoints, loaderConfig, function (err, result) {
if (err || !result) { return bundlesStream.emit('error', JSON.stringify(err)); }
toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream);
toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream);
// Remove css inlined resources
const filteredResources = resources.slice();
result.cssInlinedResources.forEach(function (resource) {
if (process.env['VSCODE_BUILD_VERBOSE']) {
log('optimizer', 'excluding inlined: ' + resource);
}
filteredResources.push('!' + resource);
});
gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream);
const bundleInfoArray: VinylFile[] = [];
if (opts.bundleInfo) {
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
}));
// Remove css inlined resources
const filteredResources = resources.slice();
result.cssInlinedResources.forEach(function (resource) {
if (process.env['VSCODE_BUILD_VERBOSE']) {
log('optimizer', 'excluding inlined: ' + resource);
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
filteredResources.push('!' + resource);
});
gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream);
const result = es.merge(
loader(src, bundledFileHeader, bundleLoader, opts.externalLoaderInfo),
bundlesStream,
resourcesStream,
bundleInfoStream
);
const bundleInfoArray: VinylFile[] = [];
if (opts.bundleInfo) {
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
});
return result
.pipe(sourcemaps.write('./', {
sourceRoot: undefined,
addComment: true,
includeContent: true
}))
.pipe(opts.languages && opts.languages.length ? processNlsFiles({
fileHeader: bundledFileHeader,
languages: opts.languages
}) : es.through())
.pipe(gulp.dest(out));
const result = es.merge(
loader(src, bundledFileHeader, false, opts.externalLoaderInfo),
bundlesStream,
resourcesStream,
bundleInfoStream
);
return result
.pipe(sourcemaps.write('./', {
sourceRoot: undefined,
addComment: true,
includeContent: true
}))
.pipe(opts.languages && opts.languages.length ? processNlsFiles({
fileHeader: bundledFileHeader,
languages: opts.languages
}) : es.through());
}
export interface IOptimizeCommonJSTaskOpts {
/**
* The paths to consider for optimizing.
*/
entryPoints: string[];
/**
* The folder to read files from.
*/
src: string;
/**
* ESBuild `platform` option: https://esbuild.github.io/api/#platform
*/
platform: 'browser' | 'node' | 'neutral';
/**
* ESBuild `external` option: https://esbuild.github.io/api/#external
*/
external: string[];
}
function optimizeCommonJSTask(opts: IOptimizeCommonJSTaskOpts): NodeJS.ReadWriteStream {
const esbuild = require('esbuild') as typeof import('esbuild');
const src = opts.src;
const entryPoints = opts.entryPoints;
return gulp.src(entryPoints, { base: `${src}`, allowEmpty: true })
.pipe(es.map((f: any, cb) => {
esbuild.build({
entryPoints: [f.path],
bundle: true,
platform: opts.platform,
write: false,
external: opts.external
}).then(res => {
const jsFile = res.outputFiles[0];
f.contents = Buffer.from(jsFile.contents);
cb(undefined, f);
});
}));
}
export interface IOptimizeManualTaskOpts {
/**
* The paths to consider for concatenation. The entries
* will be concatenated in the order they are provided.
*/
src: string[];
/**
* Destination target to concatenate the entryPoints into.
*/
out: string;
}
function optimizeManualTask(options: IOptimizeManualTaskOpts[]): NodeJS.ReadWriteStream {
const concatenations = options.map(opt => {
return gulp
.src(opt.src)
.pipe(concat(opt.out));
});
return es.merge(...concatenations);
}
export function optimizeLoaderTask(src: string, out: string, bundleLoader: boolean, bundledFileHeader = '', externalLoaderInfo?: util.IExternalLoaderInfo): () => NodeJS.ReadWriteStream {
return () => loader(src, bundledFileHeader, bundleLoader, externalLoaderInfo).pipe(gulp.dest(out));
}
export interface IOptimizeTaskOpts {
/**
* Destination folder for the optimized files.
*/
out: string;
/**
* Optimize AMD modules (using our AMD loader).
*/
amd: IOptimizeAMDTaskOpts;
/**
* Optimize CommonJS modules (using esbuild).
*/
commonJS?: IOptimizeCommonJSTaskOpts;
/**
* Optimize manually by concatenating files.
*/
manual?: IOptimizeManualTaskOpts[];
}
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
return function () {
const optimizers = [optimizeAMDTask(opts.amd)];
if (opts.commonJS) {
optimizers.push(optimizeCommonJSTask(opts.commonJS));
}
if (opts.manual) {
optimizers.push(optimizeManualTask(opts.manual));
}
return es.merge(...optimizers).pipe(gulp.dest(opts.out));
};
}
@@ -302,10 +408,16 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) =>
const jsFile = res.outputFiles.find(f => /\.js$/.test(f.path))!;
const sourceMapFile = res.outputFiles.find(f => /\.js\.map$/.test(f.path))!;
f.contents = Buffer.from(jsFile.contents);
f.sourceMap = JSON.parse(sourceMapFile.text);
const contents = Buffer.from(jsFile.contents);
const unicodeMatch = contents.toString().match(/[^\x00-\xFF]+/g);
if (unicodeMatch) {
cb(new Error(`Found non-ascii character ${unicodeMatch[0]} in the minified output of ${f.path}. Non-ASCII characters in the output can cause performance problems when loading. Please review if you have introduced a regular expression that esbuild is not automatically converting and convert it to using unicode escape sequences.`));
} else {
f.contents = contents;
f.sourceMap = JSON.parse(sourceMapFile.text);
cb(undefined, f);
cb(undefined, f);
}
}, cb);
}),
jsFilter.restore,
+55 -25
View File
File diff suppressed because one or more lines are too long
+50 -25
View File
@@ -12,6 +12,7 @@ import * as Parser from 'tree-sitter';
import fetch from 'node-fetch';
const { typescript } = require('tree-sitter-typescript');
const product = require('../../product.json');
const packageJson = require('../../package.json');
type NlsString = { value: string; nlsKey: string };
@@ -587,17 +588,13 @@ const Languages = {
type LanguageTranslations = { [moduleName: string]: { [nlsKey: string]: string } };
type Translations = { languageId: string; languageTranslations: LanguageTranslations }[];
async function getLatestStableVersion(updateUrl: string) {
const res = await fetch(`${updateUrl}/api/update/darwin/stable/latest`);
const { name: version } = await res.json() as { name: string };
return version;
}
type Version = [number, number, number];
async function getSpecificNLS(resourceUrlTemplate: string, languageId: string, version: string) {
async function getSpecificNLS(resourceUrlTemplate: string, languageId: string, version: Version) {
const resource = {
publisher: 'ms-ceintl',
name: `vscode-language-pack-${languageId}`,
version,
version: `${version[0]}.${version[1]}.${version[2]}`,
path: 'extension/translations/main.i18n.json'
};
@@ -612,22 +609,50 @@ async function getSpecificNLS(resourceUrlTemplate: string, languageId: string, v
return result;
}
function previousVersion(version: string): string {
const [, major, minor, patch] = /^(\d+)\.(\d+)\.(\d+)$/.exec(version)!;
return `${major}.${parseInt(minor) - 1}.${patch}`;
function parseVersion(version: string): Version {
const [, major, minor, patch] = /^(\d+)\.(\d+)\.(\d+)/.exec(version)!;
return [parseInt(major), parseInt(minor), parseInt(patch)];
}
async function getNLS(resourceUrlTemplate: string, languageId: string, version: string) {
try {
return await getSpecificNLS(resourceUrlTemplate, languageId, version);
} catch (err) {
if (/\[404\]/.test(err.message)) {
console.warn(`Language pack ${languageId}@${version} is missing. Downloading previous version...`);
return await getSpecificNLS(resourceUrlTemplate, languageId, previousVersion(version));
} else {
throw err;
}
function compareVersions(a: Version, b: Version): number {
if (a[0] !== b[0]) { return a[0] - b[0]; }
if (a[1] !== b[1]) { return a[1] - b[1]; }
return a[2] - b[2];
}
async function queryVersions(serviceUrl: string, languageId: string): Promise<Version[]> {
const res = await fetch(`${serviceUrl}/extensionquery`, {
method: 'POST',
headers: {
'Accept': 'application/json;api-version=3.0-preview.1',
'Content-Type': 'application/json',
'User-Agent': 'VS Code Build',
},
body: JSON.stringify({
filters: [{ criteria: [{ filterType: 7, value: `ms-ceintl.vscode-language-pack-${languageId}` }] }],
flags: 0x1
})
});
if (res.status !== 200) {
throw new Error(`[${res.status}] Error querying for extension: ${languageId}`);
}
const result = await res.json() as { results: [{ extensions: { versions: { version: string }[] }[] }] };
return result.results[0].extensions[0].versions.map(v => parseVersion(v.version)).sort(compareVersions);
}
async function getNLS(extensionGalleryServiceUrl: string, resourceUrlTemplate: string, languageId: string, version: Version) {
const versions = await queryVersions(extensionGalleryServiceUrl, languageId);
const nextMinor: Version = [version[0], version[1] + 1, 0];
const compatibleVersions = versions.filter(v => compareVersions(v, nextMinor) < 0);
const latestCompatibleVersion = compatibleVersions.at(-1)!; // order is newest to oldest
if (!latestCompatibleVersion) {
throw new Error(`No compatible language pack found for ${languageId} for version ${version}`);
}
return await getSpecificNLS(resourceUrlTemplate, languageId, latestCompatibleVersion);
}
async function parsePolicies(): Promise<Policy[]> {
@@ -649,10 +674,10 @@ async function parsePolicies(): Promise<Policy[]> {
}
async function getTranslations(): Promise<Translations> {
const updateUrl = product.updateUrl;
const extensionGalleryServiceUrl = product.extensionsGallery?.serviceUrl;
if (!updateUrl) {
console.warn(`Skipping policy localization: No 'updateUrl' found in 'product.json'.`);
if (!extensionGalleryServiceUrl) {
console.warn(`Skipping policy localization: No 'extensionGallery.serviceUrl' found in 'product.json'.`);
return [];
}
@@ -663,11 +688,11 @@ async function getTranslations(): Promise<Translations> {
return [];
}
const version = await getLatestStableVersion(updateUrl);
const version = parseVersion(packageJson.version);
const languageIds = Object.keys(Languages);
return await Promise.all(languageIds.map(
languageId => getNLS(resourceUrlTemplate, languageId, version)
languageId => getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version)
.then(languageTranslations => ({ languageId, languageTranslations }))
));
}
+1
View File
@@ -53,3 +53,4 @@ if (require.main === module) {
process.exit(1);
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlTGF1bmNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicHJlTGF1bmNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7QUFFaEcsWUFBWTtBQUVaLDZCQUE2QjtBQUM3QixpREFBc0M7QUFDdEMsMkJBQW9DO0FBRXBDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUNoRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFFcEQsU0FBUyxVQUFVLENBQUMsT0FBZSxFQUFFLE9BQThCLEVBQUU7SUFDcEUsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUM1QyxNQUFNLEtBQUssR0FBRyxJQUFBLHFCQUFLLEVBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDekYsS0FBSyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDM0IsQ0FBQyxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLE1BQU0sQ0FBQyxNQUFjO0lBQ25DLElBQUk7UUFDSCxNQUFNLGFBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUMxQyxPQUFPLElBQUksQ0FBQztLQUNaO0lBQUMsTUFBTTtRQUNQLE9BQU8sS0FBSyxDQUFDO0tBQ2I7QUFDRixDQUFDO0FBRUQsS0FBSyxVQUFVLGlCQUFpQjtJQUMvQixJQUFJLENBQUMsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxFQUFFO1FBQ3BDLE1BQU0sVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ3ZCO0FBQ0YsQ0FBQztBQUVELEtBQUssVUFBVSxXQUFXO0lBQ3pCLE1BQU0sVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7QUFDdEMsQ0FBQztBQUVELEtBQUssVUFBVSxjQUFjO0lBQzVCLElBQUksQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7UUFDM0IsTUFBTSxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztLQUNwQztBQUNGLENBQUM7QUFFRCxLQUFLLFVBQVUsSUFBSTtJQUNsQixNQUFNLGlCQUFpQixFQUFFLENBQUM7SUFDMUIsTUFBTSxXQUFXLEVBQUUsQ0FBQztJQUNwQixNQUFNLGNBQWMsRUFBRSxDQUFDO0lBRXZCLDREQUE0RDtJQUM1RCxNQUFNLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUNoRSxNQUFNLG9CQUFvQixFQUFFLENBQUM7QUFDOUIsQ0FBQztBQUVELElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7SUFDNUIsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ2xCLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqQixDQUFDLENBQUMsQ0FBQztDQUNIIn0=
+6 -5
View File
@@ -6,18 +6,18 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.createReporter = void 0;
const es = require("event-stream");
const _ = require("underscore");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const fs = require("fs");
const path = require("path");
class ErrorLog {
id;
constructor(id) {
this.id = id;
this.allErrors = [];
this.startTime = null;
this.count = 0;
}
allErrors = [];
startTime = null;
count = 0;
onStart() {
if (this.count++ > 0) {
return;
@@ -32,7 +32,7 @@ class ErrorLog {
this.log();
}
log() {
const errors = _.flatten(this.allErrors);
const errors = this.allErrors.flat();
const seen = new Set();
errors.map(err => {
if (!seen.has(err)) {
@@ -100,3 +100,4 @@ function createReporter(id) {
return result;
}
exports.createReporter = createReporter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJyZXBvcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxtQ0FBbUM7QUFDbkMsc0NBQXNDO0FBQ3RDLDBDQUEwQztBQUMxQyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBRTdCLE1BQU0sUUFBUTtJQUNNO0lBQW5CLFlBQW1CLEVBQVU7UUFBVixPQUFFLEdBQUYsRUFBRSxDQUFRO0lBQzdCLENBQUM7SUFDRCxTQUFTLEdBQWUsRUFBRSxDQUFDO0lBQzNCLFNBQVMsR0FBa0IsSUFBSSxDQUFDO0lBQ2hDLEtBQUssR0FBRyxDQUFDLENBQUM7SUFFVixPQUFPO1FBQ04sSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ3JCLE9BQU87U0FDUDtRQUVELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN0QyxRQUFRLENBQUMsWUFBWSxVQUFVLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM1RyxDQUFDO0lBRUQsS0FBSztRQUNKLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsRUFBRTtZQUNyQixPQUFPO1NBQ1A7UUFFRCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsR0FBRztRQUNGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUUvQixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxF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
+1 -2
View File
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import * as es from 'event-stream';
import * as _ from 'underscore';
import * as fancyLog from 'fancy-log';
import * as ansiColors from 'ansi-colors';
import * as fs from 'fs';
@@ -35,7 +34,7 @@ class ErrorLog {
}
log(): void {
const errors = _.flatten(this.allErrors);
const errors = this.allErrors.flat();
const seen = new Set<string>();
errors.map(err => {
+1
View File
@@ -89,3 +89,4 @@ function rollupAngular(root) {
});
}
exports.rollupAngular = rollupAngular;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9sbHVwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicm9sbHVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLHlCQUF5QjtBQUN6QixpQ0FBaUM7QUFDakMsNkJBQTZCO0FBRTdCLDhCQUE4QjtBQUM5QixNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FBQztBQUMxRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsd0JBQXdCLENBQUMsQ0FBQztBQVVuRCxLQUFLLFVBQVUsWUFBWSxDQUFDLE9BQXVCO0lBQ2xELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7SUFDdEMsSUFBSTtRQUNILE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFDcEMsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQztRQUVoRCxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLGVBQWUsRUFBRTtZQUN4QyxTQUFTLEVBQUUsSUFBSTtTQUNmLENBQUMsQ0FBQztRQUVILE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7UUFDOUMsTUFBTSxhQUFhLEdBQUcsR0FBRyxjQUFjLE1BQU0sQ0FBQztRQUM5QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUV4QyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNyRSxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUVuRSxNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDbEMsS0FBSyxFQUFFLFNBQVM7WUFDaEIsT0FBTyxFQUFFO2dCQUNSLFdBQVcsRUFBRTtnQkFDYixRQUFRLEVBQUU7YUFDVjtZQUNE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
+1
View File
@@ -53,3 +53,4 @@ var snaps;
cp.execFileSync(mksnapshot, [wrappedInputFilepath, `--startup_blob`, startupBlobFilepath]);
}
})(snaps || (snaps = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcHNob3RMb2FkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzbmFwc2hvdExvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7QUFFaEcsSUFBVSxLQUFLLENBMkRkO0FBM0RELFdBQVUsS0FBSztJQUVkLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN6QixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0IsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pCLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUVwQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSwyQkFBMkIsT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ3JJLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQzlDLE1BQU0sSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRW5FLEVBQUU7SUFDRixJQUFJLGNBQXNCLENBQUM7SUFDM0IsSUFBSSxtQkFBMkIsQ0FBQztJQUVoQyxRQUFRLE9BQU8sQ0FBQyxRQUFRLEVBQUU7UUFDekIsS0FBSyxRQUFRO1lBQ1osY0FBYyxHQUFHLGlCQUFpQixPQUFPLENBQUMsUUFBUSw4Q0FBOEMsQ0FBQztZQUNqRyxtQkFBbUIsR0FBRyxpQkFBaUIsT0FBTyxDQUFDLFFBQVEsbUZBQW1GLENBQUM7WUFDM0ksTUFBTTtRQUVQLEtBQUssT0FBTyxDQUFDO1FBQ2IsS0FBSyxPQUFPO1lBQ1gsY0FBYyxHQUFHLFVBQVUsT0FBTyxDQUFDLFFBQVEsSUFBSSxJQUFJLGlDQUFpQyxDQUFDO1lBQ3JGLG1CQUFtQixHQUFHLFVBQVUsT0FBTyxDQUFDLFFBQVEsSUFBSSxJQUFJLG9CQUFvQixDQUFDO1lBQzdFLE1BQU07UUFFUDtZQUNDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztLQUNyQztJQUVELGNBQWMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDbkUsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFFN0UsY0FBYyxDQUFDLGNBQWMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0lBRXBELFNBQVMsY0FBYyxDQUFDLGNBQXNCLEVBQUUsbUJBQTJCO1FBRTFFLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDbEQsTUFBTSxnQkFBZ0IsR0FBRzs7OztLQUl0QixTQUFTLENBQUMsUUFBUSxFQUFFOzs7Ozs7Ozs7R0FTdEIsQ0FBQztRQUNGLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUN6RSxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDbEMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxvQkFBb0IsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXpELEVBQUUsQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUMsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO0lBQzVGLENBQUM7QUFDRixDQUFDLEVBM0RTLEtBQUssS0FBTCxLQUFLLFFBMkRkIn0=
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -212,7 +212,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void {
);
}
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
fileContents = fileContents.replace(/import ([a-zA-Z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
return `import * as ${m1} from ${m2};`;
});
+4
View File
@@ -9,6 +9,9 @@ const es = require("event-stream");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
class Entry {
name;
totalCount;
totalSize;
constructor(name, totalCount, totalSize) {
this.name = name;
this.totalCount = totalCount;
@@ -71,3 +74,4 @@ function createStatsStream(group, log) {
});
}
exports.createStatsStream = createStatsStream;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdGF0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxtQ0FBbUM7QUFDbkMsc0NBQXNDO0FBQ3RDLDBDQUEwQztBQUcxQyxNQUFNLEtBQUs7SUFDVztJQUFxQjtJQUEyQjtJQUFyRSxZQUFxQixJQUFZLEVBQVMsVUFBa0IsRUFBUyxTQUFpQjtRQUFqRSxTQUFJLEdBQUosSUFBSSxDQUFRO1FBQVMsZUFBVSxHQUFWLFVBQVUsQ0FBUTtRQUFTLGNBQVMsR0FBVCxTQUFTLENBQVE7SUFBSSxDQUFDO0lBRTNGLFFBQVEsQ0FBQyxNQUFnQjtRQUN4QixJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ1osSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTtnQkFDMUIsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFNBQVMsUUFBUSxDQUFDO2FBQy9DO2lCQUFNO2dCQUNOLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxVQUFVLGVBQWUsSUFBSSxDQUFDLFNBQVMsUUFBUSxDQUFDO2FBQzdFO1NBQ0Q7YUFBTTtZQUNOLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxDQUFDLEVBQUU7Z0JBQzFCLE9BQU8sY0FBYyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQzthQUUzRjtpQkFBTTtnQkFDTixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxHQUFHLEdBQUc7b0JBQ2xDLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQzlDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUks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
@@ -0,0 +1,34 @@
"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.getVariableNameValidator = void 0;
const fs_1 = require("fs");
const path = require("path");
const RE_VAR_PROP = /var\(\s*(--([\w\-\.]+))/g;
let knownVariables;
function getKnownVariableNames() {
if (!knownVariables) {
const knownVariablesFileContent = (0, fs_1.readFileSync)(path.join(__dirname, './vscode-known-variables.json'), 'utf8').toString();
const knownVariablesInfo = JSON.parse(knownVariablesFileContent);
knownVariables = new Set([...knownVariablesInfo.colors, ...knownVariablesInfo.others]);
}
return knownVariables;
}
function getVariableNameValidator() {
const allVariables = getKnownVariableNames();
return (value, report) => {
RE_VAR_PROP.lastIndex = 0; // reset lastIndex just to be sure
let match;
while (match = RE_VAR_PROP.exec(value)) {
const variableName = match[1];
if (variableName && !allVariables.has(variableName)) {
report(variableName);
}
}
};
}
exports.getVariableNameValidator = getVariableNameValidator;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGVWYXJpYWJsZU5hbWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidmFsaWRhdGVWYXJpYWJsZU5hbWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLDJCQUFrQztBQUNsQyw2QkFBOEI7QUFFOUIsTUFBTSxXQUFXLEdBQUcsMEJBQTBCLENBQUM7QUFFL0MsSUFBSSxjQUF1QyxDQUFDO0FBQzVDLFNBQVMscUJBQXFCO0lBQzdCLElBQUksQ0FBQyxjQUFjLEVBQUU7UUFDcEIsTUFBTSx5QkFBeUIsR0FBRyxJQUFBLGlCQUFZLEVBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsK0JBQStCLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN6SCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUNqRSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxHQUFHLGtCQUFrQixDQUFDLE1BQU0sQ0FBYSxDQUFDLENBQUM7S0FDbkc7SUFDRCxPQUFPLGNBQWMsQ0FBQztBQUN2QixDQUFDO0FBTUQsU0FBZ0Isd0JBQXdCO0lBQ3ZDLE1BQU0sWUFBWSxHQUFHLHFCQUFxQixFQUFFLENBQUM7SUFDN0MsT0FBTyxDQUFDLEtBQWEsRUFBRSxNQUF3QyxFQUFFLEVBQUU7UUFDbEUsV0FBVyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxrQ0FBa0M7UUFDN0QsSUFBSSxLQUFLLENBQUM7UUFDVixPQUFPLEtBQUssR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3ZDLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5QixJQUFJLFlBQVksSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUU7Z0JBQ3BELE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUNyQjtTQUNEO0lBQ0YsQ0FBQyxDQUFDO0FBQ0gsQ0FBQztBQVpELDREQVlDIn0=
@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { readFileSync } from 'fs';
import path = require('path');
const RE_VAR_PROP = /var\(\s*(--([\w\-\.]+))/g;
let knownVariables: Set<string> | undefined;
function getKnownVariableNames() {
if (!knownVariables) {
const knownVariablesFileContent = readFileSync(path.join(__dirname, './vscode-known-variables.json'), 'utf8').toString();
const knownVariablesInfo = JSON.parse(knownVariablesFileContent);
knownVariables = new Set([...knownVariablesInfo.colors, ...knownVariablesInfo.others] as string[]);
}
return knownVariables;
}
export interface IValidator {
(value: string, report: (message: string) => void): void;
}
export function getVariableNameValidator(): IValidator {
const allVariables = getKnownVariableNames();
return (value: string, report: (unknwnVariable: string) => void) => {
RE_VAR_PROP.lastIndex = 0; // reset lastIndex just to be sure
let match;
while (match = RE_VAR_PROP.exec(value)) {
const variableName = match[1];
if (variableName && !allVariables.has(variableName)) {
report(variableName);
}
}
};
}
@@ -0,0 +1,744 @@
{
"colors": [
"--vscode-activityBar-activeBackground",
"--vscode-activityBar-activeBorder",
"--vscode-activityBar-activeFocusBorder",
"--vscode-activityBar-background",
"--vscode-activityBar-border",
"--vscode-activityBar-dropBorder",
"--vscode-activityBar-foreground",
"--vscode-activityBar-inactiveForeground",
"--vscode-activityBarBadge-background",
"--vscode-activityBarBadge-foreground",
"--vscode-badge-background",
"--vscode-badge-foreground",
"--vscode-banner-background",
"--vscode-banner-foreground",
"--vscode-banner-iconForeground",
"--vscode-breadcrumb-activeSelectionForeground",
"--vscode-breadcrumb-background",
"--vscode-breadcrumb-focusForeground",
"--vscode-breadcrumb-foreground",
"--vscode-breadcrumbPicker-background",
"--vscode-button-background",
"--vscode-button-border",
"--vscode-button-foreground",
"--vscode-button-hoverBackground",
"--vscode-button-secondaryBackground",
"--vscode-button-secondaryForeground",
"--vscode-button-secondaryHoverBackground",
"--vscode-button-separator",
"--vscode-charts-blue",
"--vscode-charts-foreground",
"--vscode-charts-green",
"--vscode-charts-lines",
"--vscode-charts-orange",
"--vscode-charts-purple",
"--vscode-charts-red",
"--vscode-charts-yellow",
"--vscode-chat-requestBackground",
"--vscode-chat-requestBorder",
"--vscode-checkbox-background",
"--vscode-checkbox-border",
"--vscode-checkbox-foreground",
"--vscode-checkbox-selectBackground",
"--vscode-checkbox-selectBorder",
"--vscode-commandCenter-activeBackground",
"--vscode-commandCenter-activeBorder",
"--vscode-commandCenter-activeForeground",
"--vscode-commandCenter-background",
"--vscode-commandCenter-border",
"--vscode-commandCenter-foreground",
"--vscode-commandCenter-inactiveBorder",
"--vscode-commandCenter-inactiveForeground",
"--vscode-commentsView-resolvedIcon",
"--vscode-commentsView-unresolvedIcon",
"--vscode-contrastActiveBorder",
"--vscode-contrastBorder",
"--vscode-debugConsole-errorForeground",
"--vscode-debugConsole-infoForeground",
"--vscode-debugConsole-sourceForeground",
"--vscode-debugConsole-warningForeground",
"--vscode-debugConsoleInputIcon-foreground",
"--vscode-debugExceptionWidget-background",
"--vscode-debugExceptionWidget-border",
"--vscode-debugIcon-breakpointCurrentStackframeForeground",
"--vscode-debugIcon-breakpointDisabledForeground",
"--vscode-debugIcon-breakpointForeground",
"--vscode-debugIcon-breakpointStackframeForeground",
"--vscode-debugIcon-breakpointUnverifiedForeground",
"--vscode-debugIcon-continueForeground",
"--vscode-debugIcon-disconnectForeground",
"--vscode-debugIcon-pauseForeground",
"--vscode-debugIcon-restartForeground",
"--vscode-debugIcon-startForeground",
"--vscode-debugIcon-stepBackForeground",
"--vscode-debugIcon-stepIntoForeground",
"--vscode-debugIcon-stepOutForeground",
"--vscode-debugIcon-stepOverForeground",
"--vscode-debugIcon-stopForeground",
"--vscode-debugTokenExpression-boolean",
"--vscode-debugTokenExpression-error",
"--vscode-debugTokenExpression-name",
"--vscode-debugTokenExpression-number",
"--vscode-debugTokenExpression-string",
"--vscode-debugTokenExpression-value",
"--vscode-debugToolBar-background",
"--vscode-debugToolBar-border",
"--vscode-debugView-exceptionLabelBackground",
"--vscode-debugView-exceptionLabelForeground",
"--vscode-debugView-stateLabelBackground",
"--vscode-debugView-stateLabelForeground",
"--vscode-debugView-valueChangedHighlight",
"--vscode-descriptionForeground",
"--vscode-diffEditor-border",
"--vscode-diffEditor-diagonalFill",
"--vscode-diffEditor-insertedLineBackground",
"--vscode-diffEditor-insertedTextBackground",
"--vscode-diffEditor-insertedTextBorder",
"--vscode-diffEditor-removedLineBackground",
"--vscode-diffEditor-removedTextBackground",
"--vscode-diffEditor-removedTextBorder",
"--vscode-diffEditor-unchangedRegionBackground",
"--vscode-diffEditorGutter-insertedLineBackground",
"--vscode-diffEditorGutter-removedLineBackground",
"--vscode-diffEditorOverview-insertedForeground",
"--vscode-diffEditorOverview-removedForeground",
"--vscode-disabledForeground",
"--vscode-dropdown-background",
"--vscode-dropdown-border",
"--vscode-dropdown-foreground",
"--vscode-dropdown-listBackground",
"--vscode-editor-background",
"--vscode-editor-findMatchBackground",
"--vscode-editor-findMatchBorder",
"--vscode-editor-findMatchHighlightBackground",
"--vscode-editor-findMatchHighlightBorder",
"--vscode-editor-findRangeHighlightBackground",
"--vscode-editor-findRangeHighlightBorder",
"--vscode-editor-focusedStackFrameHighlightBackground",
"--vscode-editor-foldBackground",
"--vscode-editor-foreground",
"--vscode-editor-hoverHighlightBackground",
"--vscode-editor-inactiveSelectionBackground",
"--vscode-editor-inlineValuesBackground",
"--vscode-editor-inlineValuesForeground",
"--vscode-editor-lineHighlightBackground",
"--vscode-editor-lineHighlightBorder",
"--vscode-editor-linkedEditingBackground",
"--vscode-editor-rangeHighlightBackground",
"--vscode-editor-rangeHighlightBorder",
"--vscode-editor-selectionBackground",
"--vscode-editor-selectionForeground",
"--vscode-editor-selectionHighlightBackground",
"--vscode-editor-selectionHighlightBorder",
"--vscode-editor-snippetFinalTabstopHighlightBackground",
"--vscode-editor-snippetFinalTabstopHighlightBorder",
"--vscode-editor-snippetTabstopHighlightBackground",
"--vscode-editor-snippetTabstopHighlightBorder",
"--vscode-editor-stackFrameHighlightBackground",
"--vscode-editor-symbolHighlightBackground",
"--vscode-editor-symbolHighlightBorder",
"--vscode-editor-wordHighlightBackground",
"--vscode-editor-wordHighlightBorder",
"--vscode-editor-wordHighlightStrongBackground",
"--vscode-editor-wordHighlightStrongBorder",
"--vscode-editor-wordHighlightTextBackground",
"--vscode-editor-wordHighlightTextBorder",
"--vscode-editorActiveLineNumber-foreground",
"--vscode-editorBracketHighlight-foreground1",
"--vscode-editorBracketHighlight-foreground2",
"--vscode-editorBracketHighlight-foreground3",
"--vscode-editorBracketHighlight-foreground4",
"--vscode-editorBracketHighlight-foreground5",
"--vscode-editorBracketHighlight-foreground6",
"--vscode-editorBracketHighlight-unexpectedBracket-foreground",
"--vscode-editorBracketMatch-background",
"--vscode-editorBracketMatch-border",
"--vscode-editorBracketPairGuide-activeBackground1",
"--vscode-editorBracketPairGuide-activeBackground2",
"--vscode-editorBracketPairGuide-activeBackground3",
"--vscode-editorBracketPairGuide-activeBackground4",
"--vscode-editorBracketPairGuide-activeBackground5",
"--vscode-editorBracketPairGuide-activeBackground6",
"--vscode-editorBracketPairGuide-background1",
"--vscode-editorBracketPairGuide-background2",
"--vscode-editorBracketPairGuide-background3",
"--vscode-editorBracketPairGuide-background4",
"--vscode-editorBracketPairGuide-background5",
"--vscode-editorBracketPairGuide-background6",
"--vscode-editorCodeLens-foreground",
"--vscode-editorCommentsWidget-rangeActiveBackground",
"--vscode-editorCommentsWidget-rangeActiveBorder",
"--vscode-editorCommentsWidget-rangeBackground",
"--vscode-editorCommentsWidget-rangeBorder",
"--vscode-editorCommentsWidget-resolvedBorder",
"--vscode-editorCommentsWidget-unresolvedBorder",
"--vscode-editorCursor-background",
"--vscode-editorCursor-foreground",
"--vscode-editorError-background",
"--vscode-editorError-border",
"--vscode-editorError-foreground",
"--vscode-editorGhostText-background",
"--vscode-editorGhostText-border",
"--vscode-editorGhostText-foreground",
"--vscode-editorGroup-border",
"--vscode-editorGroup-dropBackground",
"--vscode-editorGroup-dropIntoPromptBackground",
"--vscode-editorGroup-dropIntoPromptBorder",
"--vscode-editorGroup-dropIntoPromptForeground",
"--vscode-editorGroup-emptyBackground",
"--vscode-editorGroup-focusedEmptyBorder",
"--vscode-editorGroupHeader-border",
"--vscode-editorGroupHeader-noTabsBackground",
"--vscode-editorGroupHeader-tabsBackground",
"--vscode-editorGroupHeader-tabsBorder",
"--vscode-editorGutter-addedBackground",
"--vscode-editorGutter-background",
"--vscode-editorGutter-commentGlyphForeground",
"--vscode-editorGutter-commentRangeForeground",
"--vscode-editorGutter-commentUnresolvedGlyphForeground",
"--vscode-editorGutter-deletedBackground",
"--vscode-editorGutter-foldingControlForeground",
"--vscode-editorGutter-modifiedBackground",
"--vscode-editorHint-border",
"--vscode-editorHint-foreground",
"--vscode-editorHoverWidget-background",
"--vscode-editorHoverWidget-border",
"--vscode-editorHoverWidget-foreground",
"--vscode-editorHoverWidget-highlightForeground",
"--vscode-editorHoverWidget-statusBarBackground",
"--vscode-editorIndentGuide-activeBackground",
"--vscode-editorIndentGuide-background",
"--vscode-editorInfo-background",
"--vscode-editorInfo-border",
"--vscode-editorInfo-foreground",
"--vscode-editorInlayHint-background",
"--vscode-editorInlayHint-foreground",
"--vscode-editorInlayHint-parameterBackground",
"--vscode-editorInlayHint-parameterForeground",
"--vscode-editorInlayHint-typeBackground",
"--vscode-editorInlayHint-typeForeground",
"--vscode-editorLightBulb-foreground",
"--vscode-editorLightBulbAutoFix-foreground",
"--vscode-editorLineNumber-activeForeground",
"--vscode-editorLineNumber-dimmedForeground",
"--vscode-editorLineNumber-foreground",
"--vscode-editorLink-activeForeground",
"--vscode-editorMarkerNavigation-background",
"--vscode-editorMarkerNavigationError-background",
"--vscode-editorMarkerNavigationError-headerBackground",
"--vscode-editorMarkerNavigationInfo-background",
"--vscode-editorMarkerNavigationInfo-headerBackground",
"--vscode-editorMarkerNavigationWarning-background",
"--vscode-editorMarkerNavigationWarning-headerBackground",
"--vscode-editorOverviewRuler-addedForeground",
"--vscode-editorOverviewRuler-background",
"--vscode-editorOverviewRuler-border",
"--vscode-editorOverviewRuler-bracketMatchForeground",
"--vscode-editorOverviewRuler-commentForeground",
"--vscode-editorOverviewRuler-commentUnresolvedForeground",
"--vscode-editorOverviewRuler-commonContentForeground",
"--vscode-editorOverviewRuler-currentContentForeground",
"--vscode-editorOverviewRuler-deletedForeground",
"--vscode-editorOverviewRuler-errorForeground",
"--vscode-editorOverviewRuler-findMatchForeground",
"--vscode-editorOverviewRuler-incomingContentForeground",
"--vscode-editorOverviewRuler-infoForeground",
"--vscode-editorOverviewRuler-modifiedForeground",
"--vscode-editorOverviewRuler-rangeHighlightForeground",
"--vscode-editorOverviewRuler-selectionHighlightForeground",
"--vscode-editorOverviewRuler-warningForeground",
"--vscode-editorOverviewRuler-wordHighlightForeground",
"--vscode-editorOverviewRuler-wordHighlightStrongForeground",
"--vscode-editorOverviewRuler-wordHighlightTextForeground",
"--vscode-editorPane-background",
"--vscode-editorRuler-foreground",
"--vscode-editorStickyScroll-background",
"--vscode-editorStickyScrollHover-background",
"--vscode-editorSuggestWidget-background",
"--vscode-editorSuggestWidget-border",
"--vscode-editorSuggestWidget-focusHighlightForeground",
"--vscode-editorSuggestWidget-foreground",
"--vscode-editorSuggestWidget-highlightForeground",
"--vscode-editorSuggestWidget-selectedBackground",
"--vscode-editorSuggestWidget-selectedForeground",
"--vscode-editorSuggestWidget-selectedIconForeground",
"--vscode-editorSuggestWidgetStatus-foreground",
"--vscode-editorUnicodeHighlight-background",
"--vscode-editorUnicodeHighlight-border",
"--vscode-editorUnnecessaryCode-border",
"--vscode-editorUnnecessaryCode-opacity",
"--vscode-editorWarning-background",
"--vscode-editorWarning-border",
"--vscode-editorWarning-foreground",
"--vscode-editorWhitespace-foreground",
"--vscode-editorWidget-background",
"--vscode-editorWidget-border",
"--vscode-editorWidget-foreground",
"--vscode-editorWidget-resizeBorder",
"--vscode-errorForeground",
"--vscode-extensionBadge-remoteBackground",
"--vscode-extensionBadge-remoteForeground",
"--vscode-extensionButton-background",
"--vscode-extensionButton-foreground",
"--vscode-extensionButton-hoverBackground",
"--vscode-extensionButton-prominentBackground",
"--vscode-extensionButton-prominentForeground",
"--vscode-extensionButton-prominentHoverBackground",
"--vscode-extensionButton-separator",
"--vscode-extensionIcon-preReleaseForeground",
"--vscode-extensionIcon-sponsorForeground",
"--vscode-extensionIcon-starForeground",
"--vscode-extensionIcon-verifiedForeground",
"--vscode-focusBorder",
"--vscode-foreground",
"--vscode-icon-foreground",
"--vscode-input-background",
"--vscode-input-border",
"--vscode-input-foreground",
"--vscode-input-placeholderForeground",
"--vscode-inputOption-activeBackground",
"--vscode-inputOption-activeBorder",
"--vscode-inputOption-activeForeground",
"--vscode-inputOption-hoverBackground",
"--vscode-inputValidation-errorBackground",
"--vscode-inputValidation-errorBorder",
"--vscode-inputValidation-errorForeground",
"--vscode-inputValidation-infoBackground",
"--vscode-inputValidation-infoBorder",
"--vscode-inputValidation-infoForeground",
"--vscode-inputValidation-warningBackground",
"--vscode-inputValidation-warningBorder",
"--vscode-inputValidation-warningForeground",
"--vscode-interactiveEditor-border",
"--vscode-interactiveEditor-regionHighlight",
"--vscode-interactiveEditor-shadow",
"--vscode-interactiveEditorDiff-inserted",
"--vscode-interactiveEditorDiff-removed",
"--vscode-interactiveEditorInput-background",
"--vscode-interactiveEditorInput-border",
"--vscode-interactiveEditorInput-focusBorder",
"--vscode-interactiveEditorInput-placeholderForeground",
"--vscode-keybindingLabel-background",
"--vscode-keybindingLabel-border",
"--vscode-keybindingLabel-bottomBorder",
"--vscode-keybindingLabel-foreground",
"--vscode-keybindingTable-headerBackground",
"--vscode-keybindingTable-rowsBackground",
"--vscode-list-activeSelectionBackground",
"--vscode-list-activeSelectionForeground",
"--vscode-list-activeSelectionIconForeground",
"--vscode-list-deemphasizedForeground",
"--vscode-list-dropBackground",
"--vscode-list-errorForeground",
"--vscode-list-filterMatchBackground",
"--vscode-list-filterMatchBorder",
"--vscode-list-focusAndSelectionOutline",
"--vscode-list-focusBackground",
"--vscode-list-focusForeground",
"--vscode-list-focusHighlightForeground",
"--vscode-list-focusOutline",
"--vscode-list-highlightForeground",
"--vscode-list-hoverBackground",
"--vscode-list-hoverForeground",
"--vscode-list-inactiveFocusBackground",
"--vscode-list-inactiveFocusOutline",
"--vscode-list-inactiveSelectionBackground",
"--vscode-list-inactiveSelectionForeground",
"--vscode-list-inactiveSelectionIconForeground",
"--vscode-list-invalidItemForeground",
"--vscode-list-warningForeground",
"--vscode-listFilterWidget-background",
"--vscode-listFilterWidget-noMatchesOutline",
"--vscode-listFilterWidget-outline",
"--vscode-listFilterWidget-shadow",
"--vscode-menu-background",
"--vscode-menu-border",
"--vscode-menu-foreground",
"--vscode-menu-selectionBackground",
"--vscode-menu-selectionBorder",
"--vscode-menu-selectionForeground",
"--vscode-menu-separatorBackground",
"--vscode-menubar-selectionBackground",
"--vscode-menubar-selectionBorder",
"--vscode-menubar-selectionForeground",
"--vscode-merge-border",
"--vscode-merge-commonContentBackground",
"--vscode-merge-commonHeaderBackground",
"--vscode-merge-currentContentBackground",
"--vscode-merge-currentHeaderBackground",
"--vscode-merge-incomingContentBackground",
"--vscode-merge-incomingHeaderBackground",
"--vscode-mergeEditor-change-background",
"--vscode-mergeEditor-change-word-background",
"--vscode-mergeEditor-changeBase-background",
"--vscode-mergeEditor-changeBase-word-background",
"--vscode-mergeEditor-conflict-handled-minimapOverViewRuler",
"--vscode-mergeEditor-conflict-handledFocused-border",
"--vscode-mergeEditor-conflict-handledUnfocused-border",
"--vscode-mergeEditor-conflict-input1-background",
"--vscode-mergeEditor-conflict-input2-background",
"--vscode-mergeEditor-conflict-unhandled-minimapOverViewRuler",
"--vscode-mergeEditor-conflict-unhandledFocused-border",
"--vscode-mergeEditor-conflict-unhandledUnfocused-border",
"--vscode-mergeEditor-conflictingLines-background",
"--vscode-minimap-background",
"--vscode-minimap-errorHighlight",
"--vscode-minimap-findMatchHighlight",
"--vscode-minimap-foregroundOpacity",
"--vscode-minimap-selectionHighlight",
"--vscode-minimap-selectionOccurrenceHighlight",
"--vscode-minimap-warningHighlight",
"--vscode-minimapGutter-addedBackground",
"--vscode-minimapGutter-deletedBackground",
"--vscode-minimapGutter-modifiedBackground",
"--vscode-minimapSlider-activeBackground",
"--vscode-minimapSlider-background",
"--vscode-minimapSlider-hoverBackground",
"--vscode-notebook-cellBorderColor",
"--vscode-notebook-cellEditorBackground",
"--vscode-notebook-cellHoverBackground",
"--vscode-notebook-cellInsertionIndicator",
"--vscode-notebook-cellStatusBarItemHoverBackground",
"--vscode-notebook-cellToolbarSeparator",
"--vscode-notebook-editorBackground",
"--vscode-notebook-focusedCellBackground",
"--vscode-notebook-focusedCellBorder",
"--vscode-notebook-focusedEditorBorder",
"--vscode-notebook-inactiveFocusedCellBorder",
"--vscode-notebook-inactiveSelectedCellBorder",
"--vscode-notebook-outputContainerBackgroundColor",
"--vscode-notebook-outputContainerBorderColor",
"--vscode-notebook-selectedCellBackground",
"--vscode-notebook-selectedCellBorder",
"--vscode-notebook-symbolHighlightBackground",
"--vscode-notebookEditorOverviewRuler-runningCellForeground",
"--vscode-notebookScrollbarSlider-activeBackground",
"--vscode-notebookScrollbarSlider-background",
"--vscode-notebookScrollbarSlider-hoverBackground",
"--vscode-notebookStatusErrorIcon-foreground",
"--vscode-notebookStatusRunningIcon-foreground",
"--vscode-notebookStatusSuccessIcon-foreground",
"--vscode-notificationCenter-border",
"--vscode-notificationCenterHeader-background",
"--vscode-notificationCenterHeader-foreground",
"--vscode-notificationLink-foreground",
"--vscode-notificationToast-border",
"--vscode-notifications-background",
"--vscode-notifications-border",
"--vscode-notifications-foreground",
"--vscode-notificationsErrorIcon-foreground",
"--vscode-notificationsInfoIcon-foreground",
"--vscode-notificationsWarningIcon-foreground",
"--vscode-panel-background",
"--vscode-panel-border",
"--vscode-panel-dropBorder",
"--vscode-panelInput-border",
"--vscode-panelSection-border",
"--vscode-panelSection-dropBackground",
"--vscode-panelSectionHeader-background",
"--vscode-panelSectionHeader-border",
"--vscode-panelSectionHeader-foreground",
"--vscode-panelTitle-activeBorder",
"--vscode-panelTitle-activeForeground",
"--vscode-panelTitle-inactiveForeground",
"--vscode-peekView-border",
"--vscode-peekViewEditor-background",
"--vscode-peekViewEditor-matchHighlightBackground",
"--vscode-peekViewEditor-matchHighlightBorder",
"--vscode-peekViewEditorGutter-background",
"--vscode-peekViewEditorStickyScroll-background",
"--vscode-peekViewResult-background",
"--vscode-peekViewResult-fileForeground",
"--vscode-peekViewResult-lineForeground",
"--vscode-peekViewResult-matchHighlightBackground",
"--vscode-peekViewResult-selectionBackground",
"--vscode-peekViewResult-selectionForeground",
"--vscode-peekViewTitle-background",
"--vscode-peekViewTitleDescription-foreground",
"--vscode-peekViewTitleLabel-foreground",
"--vscode-pickerGroup-border",
"--vscode-pickerGroup-foreground",
"--vscode-ports-iconRunningProcessForeground",
"--vscode-problemsErrorIcon-foreground",
"--vscode-problemsInfoIcon-foreground",
"--vscode-problemsWarningIcon-foreground",
"--vscode-profileBadge-background",
"--vscode-profileBadge-foreground",
"--vscode-progressBar-background",
"--vscode-quickInput-background",
"--vscode-quickInput-foreground",
"--vscode-quickInput-list-focusBackground",
"--vscode-quickInputList-focusBackground",
"--vscode-quickInputList-focusForeground",
"--vscode-quickInputList-focusIconForeground",
"--vscode-quickInputTitle-background",
"--vscode-sash-hoverBorder",
"--vscode-scm-providerBorder",
"--vscode-scrollbar-shadow",
"--vscode-scrollbarSlider-activeBackground",
"--vscode-scrollbarSlider-background",
"--vscode-scrollbarSlider-hoverBackground",
"--vscode-search-resultsInfoForeground",
"--vscode-searchEditor-findMatchBackground",
"--vscode-searchEditor-findMatchBorder",
"--vscode-searchEditor-textInputBorder",
"--vscode-selection-background",
"--vscode-settings-checkboxBackground",
"--vscode-settings-checkboxBorder",
"--vscode-settings-checkboxForeground",
"--vscode-settings-dropdownBackground",
"--vscode-settings-dropdownBorder",
"--vscode-settings-dropdownForeground",
"--vscode-settings-dropdownListBorder",
"--vscode-settings-focusedRowBackground",
"--vscode-settings-focusedRowBorder",
"--vscode-settings-headerBorder",
"--vscode-settings-headerForeground",
"--vscode-settings-modifiedItemIndicator",
"--vscode-settings-numberInputBackground",
"--vscode-settings-numberInputBorder",
"--vscode-settings-numberInputForeground",
"--vscode-settings-rowHoverBackground",
"--vscode-settings-sashBorder",
"--vscode-settings-settingsHeaderHoverForeground",
"--vscode-settings-textInputBackground",
"--vscode-settings-textInputBorder",
"--vscode-settings-textInputForeground",
"--vscode-sideBar-background",
"--vscode-sideBar-border",
"--vscode-sideBar-dropBackground",
"--vscode-sideBar-foreground",
"--vscode-sideBarSectionHeader-background",
"--vscode-sideBarSectionHeader-border",
"--vscode-sideBarSectionHeader-foreground",
"--vscode-sideBarTitle-foreground",
"--vscode-sideBySideEditor-horizontalBorder",
"--vscode-sideBySideEditor-verticalBorder",
"--vscode-statusBar-background",
"--vscode-statusBar-border",
"--vscode-statusBar-debuggingBackground",
"--vscode-statusBar-debuggingBorder",
"--vscode-statusBar-debuggingForeground",
"--vscode-statusBar-focusBorder",
"--vscode-statusBar-foreground",
"--vscode-statusBar-noFolderBackground",
"--vscode-statusBar-noFolderBorder",
"--vscode-statusBar-noFolderForeground",
"--vscode-statusBar-offlineBackground",
"--vscode-statusBar-offlineForeground",
"--vscode-statusBarItem-activeBackground",
"--vscode-statusBarItem-compactHoverBackground",
"--vscode-statusBarItem-errorBackground",
"--vscode-statusBarItem-errorForeground",
"--vscode-statusBarItem-focusBorder",
"--vscode-statusBarItem-hoverBackground",
"--vscode-statusBarItem-prominentBackground",
"--vscode-statusBarItem-prominentForeground",
"--vscode-statusBarItem-prominentHoverBackground",
"--vscode-statusBarItem-remoteBackground",
"--vscode-statusBarItem-remoteForeground",
"--vscode-statusBarItem-warningBackground",
"--vscode-statusBarItem-warningForeground",
"--vscode-symbolIcon-arrayForeground",
"--vscode-symbolIcon-booleanForeground",
"--vscode-symbolIcon-classForeground",
"--vscode-symbolIcon-colorForeground",
"--vscode-symbolIcon-constantForeground",
"--vscode-symbolIcon-constructorForeground",
"--vscode-symbolIcon-enumeratorForeground",
"--vscode-symbolIcon-enumeratorMemberForeground",
"--vscode-symbolIcon-eventForeground",
"--vscode-symbolIcon-fieldForeground",
"--vscode-symbolIcon-fileForeground",
"--vscode-symbolIcon-folderForeground",
"--vscode-symbolIcon-functionForeground",
"--vscode-symbolIcon-interfaceForeground",
"--vscode-symbolIcon-keyForeground",
"--vscode-symbolIcon-keywordForeground",
"--vscode-symbolIcon-methodForeground",
"--vscode-symbolIcon-moduleForeground",
"--vscode-symbolIcon-namespaceForeground",
"--vscode-symbolIcon-nullForeground",
"--vscode-symbolIcon-numberForeground",
"--vscode-symbolIcon-objectForeground",
"--vscode-symbolIcon-operatorForeground",
"--vscode-symbolIcon-packageForeground",
"--vscode-symbolIcon-propertyForeground",
"--vscode-symbolIcon-referenceForeground",
"--vscode-symbolIcon-snippetForeground",
"--vscode-symbolIcon-stringForeground",
"--vscode-symbolIcon-structForeground",
"--vscode-symbolIcon-textForeground",
"--vscode-symbolIcon-typeParameterForeground",
"--vscode-symbolIcon-unitForeground",
"--vscode-symbolIcon-variableForeground",
"--vscode-tab-activeBackground",
"--vscode-tab-activeBorder",
"--vscode-tab-activeBorderTop",
"--vscode-tab-activeForeground",
"--vscode-tab-activeModifiedBorder",
"--vscode-tab-border",
"--vscode-tab-hoverBackground",
"--vscode-tab-hoverBorder",
"--vscode-tab-hoverForeground",
"--vscode-tab-inactiveBackground",
"--vscode-tab-inactiveForeground",
"--vscode-tab-inactiveModifiedBorder",
"--vscode-tab-lastPinnedBorder",
"--vscode-tab-unfocusedActiveBackground",
"--vscode-tab-unfocusedActiveBorder",
"--vscode-tab-unfocusedActiveBorderTop",
"--vscode-tab-unfocusedActiveForeground",
"--vscode-tab-unfocusedActiveModifiedBorder",
"--vscode-tab-unfocusedHoverBackground",
"--vscode-tab-unfocusedHoverBorder",
"--vscode-tab-unfocusedHoverForeground",
"--vscode-tab-unfocusedInactiveBackground",
"--vscode-tab-unfocusedInactiveForeground",
"--vscode-tab-unfocusedInactiveModifiedBorder",
"--vscode-terminal-ansiBlack",
"--vscode-terminal-ansiBlue",
"--vscode-terminal-ansiBrightBlack",
"--vscode-terminal-ansiBrightBlue",
"--vscode-terminal-ansiBrightCyan",
"--vscode-terminal-ansiBrightGreen",
"--vscode-terminal-ansiBrightMagenta",
"--vscode-terminal-ansiBrightRed",
"--vscode-terminal-ansiBrightWhite",
"--vscode-terminal-ansiBrightYellow",
"--vscode-terminal-ansiCyan",
"--vscode-terminal-ansiGreen",
"--vscode-terminal-ansiMagenta",
"--vscode-terminal-ansiRed",
"--vscode-terminal-ansiWhite",
"--vscode-terminal-ansiYellow",
"--vscode-terminal-background",
"--vscode-terminal-border",
"--vscode-terminal-dropBackground",
"--vscode-terminal-findMatchBackground",
"--vscode-terminal-findMatchBorder",
"--vscode-terminal-findMatchHighlightBackground",
"--vscode-terminal-findMatchHighlightBorder",
"--vscode-terminal-foreground",
"--vscode-terminal-hoverHighlightBackground",
"--vscode-terminal-inactiveSelectionBackground",
"--vscode-terminal-selectionBackground",
"--vscode-terminal-selectionForeground",
"--vscode-terminal-tab-activeBorder",
"--vscode-terminalCommandDecoration-defaultBackground",
"--vscode-terminalCommandDecoration-errorBackground",
"--vscode-terminalCommandDecoration-successBackground",
"--vscode-terminalCursor-background",
"--vscode-terminalCursor-foreground",
"--vscode-terminalOverviewRuler-cursorForeground",
"--vscode-terminalOverviewRuler-findMatchForeground",
"--vscode-testing-iconErrored",
"--vscode-testing-iconFailed",
"--vscode-testing-iconPassed",
"--vscode-testing-iconQueued",
"--vscode-testing-iconSkipped",
"--vscode-testing-iconUnset",
"--vscode-testing-message-error-decorationForeground",
"--vscode-testing-message-error-lineBackground",
"--vscode-testing-message-info-decorationForeground",
"--vscode-testing-message-info-lineBackground",
"--vscode-testing-peekBorder",
"--vscode-testing-peekHeaderBackground",
"--vscode-testing-runAction",
"--vscode-textBlockQuote-background",
"--vscode-textBlockQuote-border",
"--vscode-textCodeBlock-background",
"--vscode-textLink-activeForeground",
"--vscode-textLink-foreground",
"--vscode-textPreformat-foreground",
"--vscode-textSeparator-foreground",
"--vscode-titleBar-activeBackground",
"--vscode-titleBar-activeForeground",
"--vscode-titleBar-border",
"--vscode-titleBar-inactiveBackground",
"--vscode-titleBar-inactiveForeground",
"--vscode-toolbar-activeBackground",
"--vscode-toolbar-hoverBackground",
"--vscode-toolbar-hoverOutline",
"--vscode-tree-inactiveIndentGuidesStroke",
"--vscode-tree-indentGuidesStroke",
"--vscode-tree-tableColumnsBorder",
"--vscode-tree-tableOddRowsBackground",
"--vscode-walkThrough-embeddedEditorBackground",
"--vscode-walkthrough-stepTitle-foreground",
"--vscode-welcomePage-background",
"--vscode-welcomePage-progress-background",
"--vscode-welcomePage-progress-foreground",
"--vscode-welcomePage-tileBackground",
"--vscode-welcomePage-tileBorder",
"--vscode-welcomePage-tileHoverBackground",
"--vscode-widget-border",
"--vscode-widget-shadow",
"--vscode-window-activeBorder",
"--vscode-window-inactiveBorder"
],
"others": [
"--background-dark",
"--background-light",
"--dropdown-padding-bottom",
"--dropdown-padding-top",
"--insert-border-color",
"--last-tab-margin-right",
"--monaco-monospace-font",
"--monaco-monospace-font",
"--notebook-cell-input-preview-font-family",
"--notebook-cell-input-preview-font-size",
"--notebook-cell-output-font-size",
"--notebook-diff-view-viewport-slider",
"--notebook-find-horizontal-padding",
"--notebook-find-width",
"--outline-element-color",
"--separator-border",
"--status-border-top-color",
"--tab-border-bottom-color",
"--tab-border-top-color",
"--tab-dirty-border-top-color",
"--tabs-border-bottom-color",
"--tab-sizing-current-width",
"--tab-sizing-fixed-max-width",
"--testMessageDecorationFontFamily",
"--testMessageDecorationFontSize",
"--title-border-bottom-color",
"--vscode-editorCodeLens-fontFamily",
"--vscode-editorCodeLens-fontFamilyDefault",
"--vscode-editorCodeLens-fontFeatureSettings",
"--vscode-editorCodeLens-fontSize",
"--vscode-editorCodeLens-lineHeight",
"--vscode-explorer-align-offset-margin-left",
"--vscode-interactive-session-foreground",
"--vscode-interactive-result-editor-background-color",
"--vscode-repl-font-family",
"--vscode-repl-font-size-for-twistie",
"--vscode-repl-font-size",
"--vscode-repl-line-height",
"--vscode-sash-hover-size",
"--vscode-sash-size",
"--window-border-color",
"--workspace-trust-check-color",
"--workspace-trust-selected-color",
"--workspace-trust-unselected-color",
"--workspace-trust-x-color",
"--z-index-notebook-cell-bottom-toolbar-container",
"--z-index-notebook-cell-editor-outline",
"--z-index-notebook-cell-expand-part-button",
"--z-index-notebook-cell-output-toolbar",
"--z-index-notebook-cell-status",
"--z-index-notebook-cell-toolbar-dropdown-active",
"--z-index-notebook-cell-toolbar",
"--z-index-notebook-folding-indicator",
"--z-index-notebook-input-collapse-condicon",
"--z-index-notebook-list-insertion-indicator",
"--z-index-notebook-output",
"--z-index-notebook-progress-bar",
"--z-index-notebook-scrollbar",
"--z-index-run-button-container",
"--zoom-factor"
]
}
+1
View File
@@ -95,3 +95,4 @@ function define(name, task) {
return task;
}
exports.define = define;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRhc2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsc0NBQXNDO0FBQ3RDLDBDQUEwQztBQW1CMUMsU0FBUyxVQUFVLENBQUMsQ0FBeUM7SUFDNUQsSUFBSSxPQUFhLENBQUUsQ0FBQyxJQUFJLEtBQUssVUFBVSxFQUFFO1FBQ3hDLE9BQU8sSUFBSSxDQUFDO0tBQ1o7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNkLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxJQUFZO0lBQ2hDLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7QUFDakMsQ0FBQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsSUFBVTtJQUNqQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxXQUFXLElBQUksYUFBYSxDQUFDO0lBQ2hFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ2pCLFFBQVEsQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztLQUNuRDtJQUNELE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNuQyxNQUFNLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QixNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ2pCLFFBQVEsQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFB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
+4 -3
View File
@@ -9,20 +9,20 @@ const i18n = require("../i18n");
suite('XLF Parser Tests', () => {
const sampleXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &amp;</source></trans-unit></body></file></xliff>';
const sampleTranslatedXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" target-language="ru" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source><target>Кнопка #1</target></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &amp;</source><target>Кнопка #2 &amp;</target></trans-unit></body></file></xliff>';
const originalFilePath = 'vs/base/common/keybinding';
const name = 'vs/base/common/keybinding';
const keys = ['key1', 'key2'];
const messages = ['Key #1', 'Key #2 &'];
const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' };
test('Keys & messages to XLF conversion', () => {
const xlf = new i18n.XLF('vscode-workbench');
xlf.addFile(originalFilePath, keys, messages);
xlf.addFile(name, keys, messages);
const xlfString = xlf.toString();
assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf);
});
test('XLF to keys & messages conversion', () => {
i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) {
assert.deepStrictEqual(resolvedFiles[0].messages, translatedMessages);
assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath);
assert.strictEqual(resolvedFiles[0].name, name);
});
});
test('JSON file source path to Transifex resource match', () => {
@@ -38,3 +38,4 @@ suite('XLF Parser Tests', () => {
assert.deepStrictEqual(i18n.getResource('vs/workbench/browser/parts/panel/panelActions'), workbench);
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaTE4bi50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaTE4bi50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7QUFFaEcsaUNBQWtDO0FBQ2xDLGdDQUFpQztBQUVqQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO0lBQzlCLE1BQU0sU0FBUyxHQUFHLGtYQUFrWCxDQUFDO0lBQ3JZLE1BQU0sbUJBQW1CLEdBQUcsaWNBQWljLENBQUM7SUFDOWQsTUFBTSxJQUFJLEdBQUcsMkJBQTJCLENBQUM7SUFDekMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDOUIsTUFBTSxRQUFRLEdBQUcsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEMsTUFBTSxrQkFBa0IsR0FBRyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxDQUFDO0lBRXRFLElBQUksQ0FBQyxtQ0FBbUMsRUFBRSxHQUFHLEVBQUU7UUFDOUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDN0MsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUVqQyxNQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ2pFLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLG1DQUFtQyxFQUFFLEdBQUcsRUFBRTtRQUM5QyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLGFBQWE7WUFDL0QsTUFBTSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLGtCQUFrQixDQUFDLENBQUM7WUFDdEUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pELENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsbURBQW1ELEVBQUUsR0FBRyxFQUFFO1FBQzlELE1BQU0sYUFBYSxHQUFXLGVBQWUsRUFDNUMsZ0JBQWdCLEdBQVcsa0JBQWtCLENBQUM7UUFFL0MsTUFBTSxRQUFRLEdBQWtCLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLEVBQzlFLGFBQWEsR0FBRyxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLEVBQ3JFLE1BQU0sR0FBRyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxFQUN0RCxJQUFJLEdBQUcsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsRUFDbEQsSUFBSSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsRUFDckQsY0FBYyxHQUFHLEVBQUUsSUFBSSxFQUFFLDJCQUEyQixFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxFQUNqRixpQkFBaUIsR0FBRyxFQUFFLElBQUksRUFBRSxnQ0FBZ0MsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsRUFDekYsU0FBUyxHQUFHLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQztRQUVqRSxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsaURBQWlELENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN0RyxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsK0NBQStDLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUN6RyxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsc0NBQXNDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN6RixNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsNkJBQTZCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5RSxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsOEJBQThCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvRSxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsMkNBQTJDLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUN0RyxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMscURBQXFELENBQUMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ25ILE1BQU0sQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQywrQ0FBK0MsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3RHLENBQUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQyxDQUFDLENBQUMifQ==
+3 -3
View File
@@ -9,14 +9,14 @@ import i18n = require('../i18n');
suite('XLF Parser Tests', () => {
const sampleXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &amp;</source></trans-unit></body></file></xliff>';
const sampleTranslatedXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" target-language="ru" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source><target>Кнопка #1</target></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &amp;</source><target>Кнопка #2 &amp;</target></trans-unit></body></file></xliff>';
const originalFilePath = 'vs/base/common/keybinding';
const name = 'vs/base/common/keybinding';
const keys = ['key1', 'key2'];
const messages = ['Key #1', 'Key #2 &'];
const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' };
test('Keys & messages to XLF conversion', () => {
const xlf = new i18n.XLF('vscode-workbench');
xlf.addFile(originalFilePath, keys, messages);
xlf.addFile(name, keys, messages);
const xlfString = xlf.toString();
assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf);
@@ -25,7 +25,7 @@ suite('XLF Parser Tests', () => {
test('XLF to keys & messages conversion', () => {
i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) {
assert.deepStrictEqual(resolvedFiles[0].messages, translatedMessages);
assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath);
assert.strictEqual(resolvedFiles[0].name, name);
});
});
File diff suppressed because one or more lines are too long
+71 -53
View File
@@ -609,58 +609,60 @@ function markNodes(ts: typeof import('typescript'), languageService: ts.Language
const nodeSourceFile = node.getSourceFile();
const loop = (node: ts.Node) => {
const [symbol, symbolImportNode] = getRealNodeSymbol(ts, checker, node);
if (symbolImportNode) {
setColor(symbolImportNode, NodeColor.Black);
const importDeclarationNode = findParentImportDeclaration(symbolImportNode);
if (importDeclarationNode && ts.isStringLiteral(importDeclarationNode.moduleSpecifier)) {
enqueueImport(importDeclarationNode, importDeclarationNode.moduleSpecifier.text);
const symbols = getRealNodeSymbol(ts, checker, node);
for (const { symbol, symbolImportNode } of symbols) {
if (symbolImportNode) {
setColor(symbolImportNode, NodeColor.Black);
const importDeclarationNode = findParentImportDeclaration(symbolImportNode);
if (importDeclarationNode && ts.isStringLiteral(importDeclarationNode.moduleSpecifier)) {
enqueueImport(importDeclarationNode, importDeclarationNode.moduleSpecifier.text);
}
}
}
if (isSymbolWithDeclarations(symbol) && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
if (isSymbolWithDeclarations(symbol) && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
for (let i = 0, len = symbol.declarations!.length; i < len; i++) { // {{SQL CARBON EDIT}} Compile fixes
const declaration = symbol.declarations![i]; // {{SQL CARBON EDIT}} Compile fixes
if (ts.isSourceFile(declaration)) {
// Do not enqueue full source files
// (they can be the declaration of a module import)
continue;
}
if (options.shakeLevel === ShakeLevel.ClassMembers && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(ts, program, checker, declaration)) {
enqueue_black(declaration.name!);
for (let j = 0; j < declaration.members.length; j++) {
const member = declaration.members[j];
const memberName = member.name ? member.name.getText() : null;
if (
ts.isConstructorDeclaration(member)
|| ts.isConstructSignatureDeclaration(member)
|| ts.isIndexSignatureDeclaration(member)
|| ts.isCallSignatureDeclaration(member)
|| memberName === '[Symbol.iterator]'
|| memberName === '[Symbol.toStringTag]'
|| memberName === 'toJSON'
|| memberName === 'toString'
|| memberName === 'dispose'// TODO: keeping all `dispose` methods
|| /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`...
) {
enqueue_black(member);
}
if (isStaticMemberWithSideEffects(ts, member)) {
enqueue_black(member);
}
if (ts.isSourceFile(declaration)) {
// Do not enqueue full source files
// (they can be the declaration of a module import)
continue;
}
// queue the heritage clauses
if (declaration.heritageClauses) {
for (const heritageClause of declaration.heritageClauses) {
enqueue_black(heritageClause);
if (options.shakeLevel === ShakeLevel.ClassMembers && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(ts, program, checker, declaration)) {
enqueue_black(declaration.name!);
for (let j = 0; j < declaration.members.length; j++) {
const member = declaration.members[j];
const memberName = member.name ? member.name.getText() : null;
if (
ts.isConstructorDeclaration(member)
|| ts.isConstructSignatureDeclaration(member)
|| ts.isIndexSignatureDeclaration(member)
|| ts.isCallSignatureDeclaration(member)
|| memberName === '[Symbol.iterator]'
|| memberName === '[Symbol.toStringTag]'
|| memberName === 'toJSON'
|| memberName === 'toString'
|| memberName === 'dispose'// TODO: keeping all `dispose` methods
|| /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`...
) {
enqueue_black(member);
}
if (isStaticMemberWithSideEffects(ts, member)) {
enqueue_black(member);
}
}
// queue the heritage clauses
if (declaration.heritageClauses) {
for (const heritageClause of declaration.heritageClauses) {
enqueue_black(heritageClause);
}
}
} else {
enqueue_black(declaration);
}
} else {
enqueue_black(declaration);
}
}
}
@@ -879,7 +881,8 @@ function findSymbolFromHeritageType(ts: typeof import('typescript'), checker: ts
return findSymbolFromHeritageType(ts, checker, type.expression);
}
if (ts.isIdentifier(type)) {
return getRealNodeSymbol(ts, checker, type)[0];
const tmp = getRealNodeSymbol(ts, checker, type);
return (tmp.length > 0 ? tmp[0].symbol : null);
}
if (ts.isPropertyAccessExpression(type)) {
return findSymbolFromHeritageType(ts, checker, type.name);
@@ -887,10 +890,17 @@ function findSymbolFromHeritageType(ts: typeof import('typescript'), checker: ts
return null;
}
class SymbolImportTuple {
constructor(
public readonly symbol: ts.Symbol | null,
public readonly symbolImportNode: ts.Declaration | null
) { }
}
/**
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
*/
function getRealNodeSymbol(ts: typeof import('typescript'), checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | null, ts.Declaration | null] {
function getRealNodeSymbol(ts: typeof import('typescript'), checker: ts.TypeChecker, node: ts.Node): SymbolImportTuple[] {
// Use some TypeScript internals to avoid code duplication
type ObjectLiteralElementWithName = ts.ObjectLiteralElement & { name: ts.PropertyName; parent: ts.ObjectLiteralExpression | ts.JsxAttributes };
@@ -923,7 +933,7 @@ function getRealNodeSymbol(ts: typeof import('typescript'), checker: ts.TypeChec
if (!ts.isShorthandPropertyAssignment(node)) {
if (node.getChildCount() !== 0) {
return [null, null];
return [];
}
}
@@ -976,10 +986,7 @@ function getRealNodeSymbol(ts: typeof import('typescript'), checker: ts.TypeChec
const type = checker.getTypeAtLocation(parent.parent);
if (name && type) {
if (type.isUnion()) {
const prop = type.types[0].getProperty(name);
if (prop) {
symbol = prop;
}
return generateMultipleSymbols(type, name, importNode);
} else {
const prop = type.getProperty(name);
if (prop) {
@@ -1011,10 +1018,21 @@ function getRealNodeSymbol(ts: typeof import('typescript'), checker: ts.TypeChec
}
if (symbol && symbol.declarations) {
return [symbol, importNode];
return [new SymbolImportTuple(symbol, importNode)];
}
return [null, null];
return [];
function generateMultipleSymbols(type: ts.UnionType, name: string, importNode: ts.Declaration | null): SymbolImportTuple[] {
const result: SymbolImportTuple[] = [];
for (const t of type.types) {
const prop = t.getProperty(name);
if (prop && prop.declarations) {
result.push(new SymbolImportTuple(prop, importNode));
}
}
return result;
}
}
/** Get the token whose text contains the position */
File diff suppressed because one or more lines are too long
+82 -5
View File
@@ -3,13 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { statSync, readFileSync } from 'fs';
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import * as utils from './utils';
import * as colors from 'ansi-colors';
import * as ts from 'typescript';
import * as Vinyl from 'vinyl';
import { RawSourceMap, SourceMapConsumer, SourceMapGenerator } from 'source-map';
export interface IConfiguration {
logFn: (topic: string, message: string) => void;
@@ -158,8 +159,81 @@ export function createTypeScriptBuilder(config: IConfiguration, projectFile: str
const dirname = path.dirname(vinyl.relative);
const tsname = (dirname === '.' ? '' : dirname + '/') + basename + '.ts';
const sourceMap = JSON.parse(sourcemapFile.text);
let sourceMap = <RawSourceMap>JSON.parse(sourcemapFile.text);
sourceMap.sources[0] = tsname.replace(/\\/g, '/');
// check for an "input source" map and combine them
// in step 1 we extract all line edit from the input source map, and
// in step 2 we apply the line edits to the typescript source map
const snapshot = host.getScriptSnapshot(fileName);
if (snapshot instanceof VinylScriptSnapshot && snapshot.sourceMap) {
const inputSMC = new SourceMapConsumer(snapshot.sourceMap);
const tsSMC = new SourceMapConsumer(sourceMap);
let didChange = false;
const smg = new SourceMapGenerator({
file: sourceMap.file,
sourceRoot: sourceMap.sourceRoot
});
// step 1
const lineEdits = new Map<number, [from: number, to: number][]>();
inputSMC.eachMapping(m => {
if (m.originalLine === m.generatedLine) {
// same line mapping
let array = lineEdits.get(m.originalLine);
if (!array) {
array = [];
lineEdits.set(m.originalLine, array);
}
array.push([m.originalColumn, m.generatedColumn]);
} else {
// NOT SUPPORTED
}
});
// step 2
tsSMC.eachMapping(m => {
didChange = true;
const edits = lineEdits.get(m.originalLine);
let originalColumnDelta = 0;
if (edits) {
for (const [from, to] of edits) {
if (to >= m.originalColumn) {
break;
}
originalColumnDelta = from - to;
}
}
smg.addMapping({
source: m.source,
name: m.name,
generated: { line: m.generatedLine, column: m.generatedColumn },
original: { line: m.originalLine, column: m.originalColumn + originalColumnDelta }
});
});
if (didChange) {
[tsSMC, inputSMC].forEach((consumer) => {
(<SourceMapConsumer & { sources: string[] }>consumer).sources.forEach((sourceFile: any) => {
(<any>smg)._sources.add(sourceFile);
const sourceContent = consumer.sourceContentFor(sourceFile);
if (sourceContent !== null) {
smg.setSourceContent(sourceFile, sourceContent);
}
});
});
sourceMap = JSON.parse(smg.toString());
// const filename = '/Users/jrieken/Code/vscode/src2/' + vinyl.relative + '.map';
// fs.promises.mkdir(path.dirname(filename), { recursive: true }).then(async () => {
// await fs.promises.writeFile(filename, smg.toString());
// await fs.promises.writeFile('/Users/jrieken/Code/vscode/src2/' + vinyl.relative, vinyl.contents);
// });
}
}
(<any>vinyl).sourceMap = sourceMap;
}
}
@@ -397,9 +471,12 @@ class VinylScriptSnapshot extends ScriptSnapshot {
private readonly _base: string;
constructor(file: Vinyl) {
readonly sourceMap?: RawSourceMap;
constructor(file: Vinyl & { sourceMap?: RawSourceMap }) {
super(file.contents!.toString(), file.stat!.mtime);
this._base = file.base;
this.sourceMap = file.sourceMap;
}
getBase(): string {
@@ -474,9 +551,9 @@ class LanguageServiceHost implements ts.LanguageServiceHost {
try {
result = new VinylScriptSnapshot(new Vinyl(<any>{
path: filename,
contents: readFileSync(filename),
contents: fs.readFileSync(filename),
base: this.getCompilationSettings().outDir,
stat: statSync(filename)
stat: fs.statSync(filename)
}));
this.addScriptSnapshot(filename, result);
} catch (e) {
File diff suppressed because one or more lines are too long
+10 -6
View File
@@ -13,7 +13,7 @@ import { strings } from './utils';
import { readFileSync, statSync } from 'fs';
import * as log from 'fancy-log';
import colors = require('ansi-colors');
import { Transpiler } from './transpiler';
import { ITranspiler, SwcTranspiler, TscTranspiler } from './transpiler';
export interface IncrementalCompiler {
(token?: any): Readable & Writable;
@@ -36,13 +36,15 @@ const _defaultOnError = (err: string) => console.log(JSON.stringify(err, null, 4
export function create(
projectPath: string,
existingOptions: Partial<ts.CompilerOptions>,
config: { verbose?: boolean; transpileOnly?: boolean; transpileOnlyIncludesDts?: boolean },
config: { verbose?: boolean; transpileOnly?: boolean; transpileOnlyIncludesDts?: boolean; transpileWithSwc?: boolean },
onError: (message: string) => void = _defaultOnError
): IncrementalCompiler {
function printDiagnostic(diag: ts.Diagnostic): void {
function printDiagnostic(diag: ts.Diagnostic | Error): void {
if (!diag.file || !diag.start) {
if (diag instanceof Error) {
onError(diag.message);
} else if (!diag.file || !diag.start) {
onError(ts.flattenDiagnosticMessageText(diag.messageText, '\n'));
} else {
const lineAndCh = diag.file.getLineAndCharacterOfPosition(diag.start);
@@ -95,7 +97,7 @@ export function create(
}
// TRANSPILE ONLY stream doing just TS to JS conversion
function createTranspileStream(transpiler: Transpiler): Readable & Writable {
function createTranspileStream(transpiler: ITranspiler): Readable & Writable {
return through(function (this: through.ThroughStream & { queue(a: any): void }, file: Vinyl) {
// give the file to the compiler
if (file.isStream()) {
@@ -126,7 +128,9 @@ export function create(
let result: IncrementalCompiler;
if (config.transpileOnly) {
const transpiler = new Transpiler(logFn, printDiagnostic, projectPath, cmdLine);
const transpiler = !config.transpileWithSwc
? new TscTranspiler(logFn, printDiagnostic, projectPath, cmdLine)
: new SwcTranspiler(logFn, printDiagnostic, projectPath, cmdLine);
result = <any>(() => createTranspileStream(transpiler));
} else {
const _builder = builder.createTypeScriptBuilder({ logFn }, projectPath, cmdLine);
File diff suppressed because one or more lines are too long
+164 -42
View File
@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as swc from '@swc/core';
import * as ts from 'typescript';
import * as threads from 'node:worker_threads';
import * as Vinyl from 'vinyl';
@@ -48,6 +49,47 @@ if (!threads.isMainThread) {
});
}
class OutputFileNameOracle {
readonly getOutputFileName: (name: string) => string;
constructor(cmdLine: ts.ParsedCommandLine, configFilePath: string) {
// very complicated logic to re-use TS internal functions to know the output path
// given a TS input path and its config
type InternalTsApi = typeof ts & {
normalizePath(path: string): string;
getOutputFileNames(commandLine: ts.ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[];
};
this.getOutputFileName = (file) => {
try {
// windows: path-sep normalizing
file = (<InternalTsApi>ts).normalizePath(file);
if (!cmdLine.options.configFilePath) {
// this is needed for the INTERNAL getOutputFileNames-call below...
cmdLine.options.configFilePath = configFilePath;
}
const isDts = file.endsWith('.d.ts');
if (isDts) {
file = file.slice(0, -5) + '.ts';
cmdLine.fileNames.push(file);
}
const outfile = (<InternalTsApi>ts).getOutputFileNames(cmdLine, file, true)[0];
if (isDts) {
cmdLine.fileNames.pop();
}
return outfile;
} catch (err) {
console.error(file, cmdLine.fileNames);
console.error(err);
throw new err;
}
};
}
}
class TranspileWorker {
private static pool = 1;
@@ -141,12 +183,18 @@ class TranspileWorker {
}
}
export interface ITranspiler {
onOutfile?: (file: Vinyl) => void;
join(): Promise<void>;
transpile(file: Vinyl): void;
}
export class Transpiler {
export class TscTranspiler implements ITranspiler {
static P = Math.floor(cpus().length * .5);
private readonly _getOutputFileName: (name: string) => string;
private readonly _outputFileNames: OutputFileNameOracle;
public onOutfile?: (file: Vinyl) => void;
@@ -160,42 +208,8 @@ export class Transpiler {
configFilePath: string,
private readonly _cmdLine: ts.ParsedCommandLine
) {
logFn('Transpile', `will use ${Transpiler.P} transpile worker`);
// very complicated logic to re-use TS internal functions to know the output path
// given a TS input path and its config
type InternalTsApi = typeof ts & {
normalizePath(path: string): string;
getOutputFileNames(commandLine: ts.ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[];
};
this._getOutputFileName = (file) => {
try {
// windows: path-sep normalizing
file = (<InternalTsApi>ts).normalizePath(file);
if (!_cmdLine.options.configFilePath) {
// this is needed for the INTERNAL getOutputFileNames-call below...
_cmdLine.options.configFilePath = configFilePath;
}
const isDts = file.endsWith('.d.ts');
if (isDts) {
file = file.slice(0, -5) + '.ts';
_cmdLine.fileNames.push(file);
}
const outfile = (<InternalTsApi>ts).getOutputFileNames(_cmdLine, file, true)[0];
if (isDts) {
_cmdLine.fileNames.pop();
}
return outfile;
} catch (err) {
console.error(file, _cmdLine.fileNames);
console.error(err);
throw new err;
}
};
logFn('Transpile', `will use ${TscTranspiler.P} transpile worker`);
this._outputFileNames = new OutputFileNameOracle(_cmdLine, configFilePath);
}
async join() {
@@ -218,7 +232,7 @@ export class Transpiler {
}
const newLen = this._queue.push(file);
if (newLen > Transpiler.P ** 2) {
if (newLen > TscTranspiler.P ** 2) {
this._consumeQueue();
}
}
@@ -232,8 +246,8 @@ export class Transpiler {
// kinda LAZYily create workers
if (this._workerPool.length === 0) {
for (let i = 0; i < Transpiler.P; i++) {
this._workerPool.push(new TranspileWorker(file => this._getOutputFileName(file)));
for (let i = 0; i < TscTranspiler.P; i++) {
this._workerPool.push(new TranspileWorker(file => this._outputFileNames.getOutputFileName(file)));
}
}
@@ -251,7 +265,7 @@ export class Transpiler {
const job = new Promise(resolve => {
const consume = () => {
const files = this._queue.splice(0, Transpiler.P);
const files = this._queue.splice(0, TscTranspiler.P);
if (files.length === 0) {
// DONE
resolve(undefined);
@@ -283,3 +297,111 @@ function _isDefaultEmpty(src: string): boolean {
.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1')
.trim().length === 0;
}
export class SwcTranspiler implements ITranspiler {
onOutfile?: ((file: Vinyl) => void) | undefined;
private readonly _outputFileNames: OutputFileNameOracle;
private _jobs: Promise<any>[] = [];
constructor(
private readonly _logFn: (topic: string, message: string) => void,
private readonly _onError: (err: any) => void,
configFilePath: string,
private readonly _cmdLine: ts.ParsedCommandLine
) {
_logFn('Transpile', `will use SWC to transpile source files`);
this._outputFileNames = new OutputFileNameOracle(_cmdLine, configFilePath);
}
async join(): Promise<void> {
const jobs = this._jobs.slice();
this._jobs.length = 0;
await Promise.allSettled(jobs);
}
transpile(file: Vinyl): void {
if (this._cmdLine.options.noEmit) {
// not doing ANYTHING here
return;
}
const tsSrc = String(file.contents);
const t1 = Date.now();
let options: swc.Options = SwcTranspiler._swcrcEsm;
if (this._cmdLine.options.module === ts.ModuleKind.AMD) {
const isAmd = /\n(import|export)/m.test(tsSrc);
if (isAmd) {
options = SwcTranspiler._swcrcAmd;
}
} else if (this._cmdLine.options.module === ts.ModuleKind.CommonJS) {
options = SwcTranspiler._swcrcCommonJS;
}
this._jobs.push(swc.transform(tsSrc, options).then(output => {
// check if output of a DTS-files isn't just "empty" and iff so
// skip this file
if (file.path.endsWith('.d.ts') && _isDefaultEmpty(output.code)) {
return;
}
const outBase = this._cmdLine.options.outDir ?? file.base;
const outPath = this._outputFileNames.getOutputFileName(file.path);
this.onOutfile!(new Vinyl({
path: outPath,
base: outBase,
contents: Buffer.from(output.code),
}));
this._logFn('Transpile', `swc took ${Date.now() - t1}ms for ${file.path}`);
}).catch(err => {
this._onError(err);
}));
}
// --- .swcrc
private static readonly _swcrcAmd: swc.Options = {
exclude: '\.js$',
jsc: {
parser: {
syntax: 'typescript',
tsx: false,
decorators: true
},
target: 'es2020',
loose: false,
minify: {
compress: false,
mangle: false
}
},
module: {
type: 'amd',
noInterop: true
},
minify: false,
};
private static readonly _swcrcCommonJS: swc.Options = {
...this._swcrcAmd,
module: {
type: 'commonjs',
importInterop: 'none'
}
};
private static readonly _swcrcEsm: swc.Options = {
...this._swcrcAmd,
module: {
type: 'es6'
}
};
}
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
declare module "gulp-buffer" {
function f(): NodeJS.ReadWriteStream;
/**
* This is required as per:
* https://github.com/microsoft/TypeScript/issues/5073
*/
namespace f {}
export = f;
}

Some files were not shown because too many files have changed in this diff Show More