Compare commits

...

298 Commits
1.4.1 ... 1.5.2

Author SHA1 Message Date
Karl Burtram
f74080c963 Bump ADS to 1.5.2 2019-03-21 22:57:32 -07:00
Raj
32cd41d076 Merge master 25b1d4b673 2019-03-21 21:38:04 -07:00
Raj
0d7d1cf375 #4618: Notebook JSON has extra } after save (#4627) 2019-03-21 21:31:53 -07:00
Chris LaFreniere
8b826063b4 Have notebook grids respond to theme change events (#4624) 2019-03-21 21:31:05 -07:00
Charles Gagnon
6a500715a7 Fix recent connections list to use <default> DB if no DB is specified by the user when a connection is made (#4564) 2019-03-15 17:34:25 -07:00
Cory Rivera
5e02486ace Check error in webhdfs.sendRequest before trying to check response code. (#4561) 2019-03-15 17:34:15 -07:00
Karl Burtram
16dbef978e Fix missing Azure account name 2019-03-15 15:40:58 -07:00
Alan Ren
f9081773dd make connectiondialog react to provider event (#4544)
* make connectiondialog react to provider event

* fix unit test error

* code review comments
2019-03-15 15:16:40 -07:00
Karl Burtram
b3799d4506 Revert "Grid scrolling bugs (#4396)"
This reverts commit ace6012c1c.
2019-03-15 14:12:18 -07:00
Karl Burtram
2ab9e4b861 Revert "change sizing behavior to allow the messages to fulling collapse down (set results to have no max height) (#4313)"
This reverts commit 7de294a58e.
2019-03-15 13:37:56 -07:00
Charles Gagnon
a1d8bae654 Fix dropdowns flickering every other time they're opened. The hide message code was being invoked which called hideContextView (the actual dropdown part) even if no message was ever displayed. Now we'll delay setting the message to null and only call hideContextView if we actually had a message to display. (#4528)
Also fixed small issue where messages that didn't have a container would throw an error when trying to call removeClass (since this.element is pulled from the container and thus was undefined.

Tested that the flicker is gone and that messages still show up correctly
2019-03-15 11:38:37 -07:00
Kevin Cunnane
b265c53f9c FIX #4513 Notebook stuck at changing kernel (#4518)
* FIX #4513 Notebook stuck at changing kernel
- Intra-provider kernel change didn't happen because we only tried changing kernel on new session creation.
- Inverted the logic (e.g. did the right thing) and renamed the method so it's clearer what we're doing & what the boolean value should be
- Manually tested all the known scenarios
2019-03-15 11:38:29 -07:00
Alan Ren
ac7d19133a use the new dataprotocol client (#4515) 2019-03-15 11:38:23 -07:00
Kevin Cunnane
ab3895a4c2 Fix #4505 Notebooks: New Notebook will not work if existing untitled notebooks are rehydrated (#4506)
* Fix #4505 Notebooks: New Notebook will not work if existing untitled notebooks are rehydrated
* Also fixes #4508
* Unify behavior across New Notebook entry points
- Use Notebook-{n} as the standard in both entry points
- Use SQL as default provider in both
- Ensure both check for other names and only use free number
2019-03-15 11:38:16 -07:00
udeeshagautam
a230e24af0 Fix for : 4471 Backup/Restore shows in Context Menu for Azure DB (#4498)
* Remove Back Restore from Cloud db's Context menu

* checking for null

* Cleaning up the check
2019-03-15 11:38:08 -07:00
Kevin Cunnane
8354ccd76d Fix #4029 Ensure changeKernels always resolves, even in error states (#4488)
* Fix #4029 Ensure changeKernels always resolves, even in error states
This is necessary to unblock reverting the kernel on canceling  Python install
- startSession now correctly sets up kernel information, since a kernel is loaded there.
- Remove call to change kernel on session initialize. This isn't needed due to refactor
- Handle kernel change failure by attempting to fall back to old kernel
- ExtensionHost $startNewSession now ensures errors are sent across the wire.
- Update AttachTo and Kernel dropdowns so they handle kernel being available. This is needed since other changes mean the session is likely ready before these get going

* Fix to handle python cancel and load existing scenarios
- Made changes to handle failure flow when Python dialog is canceled
- Made changes to handle initial load fail. Kernel and Attach To dropdowns show No Kernel / None and you can choose a kernel
- Added error wrapping in ext host so that string errors make it across and aren't lost.
2019-03-15 11:37:58 -07:00
Karl Burtram
3d60ee9030 Merge branch 'master' into release/1.5 2019-03-14 10:04:56 -07:00
Matt Irvine
7973f0f178 Disable custom title bar popup on Linux (#4478) 2019-03-14 09:28:19 -07:00
Chris LaFreniere
11f0ca371b Show running state in cell toolbar immediately when cell is run (#4484) 2019-03-13 20:04:46 -07:00
Kevin Cunnane
0131746919 Fix #4452 Notebook is reloaded with wrong kernel (#4480)
* Fix #4452 Notebook is reloaded with wrong kernel
- Await all extension registration before getting providers and providerId
To do this, we need to await way up in the NotebookInput, and promise the model that we'll have values eventually
2019-03-13 20:03:01 -07:00
Chris LaFreniere
5774b1f69a remove ugly border around text cells (#4481) 2019-03-13 19:24:39 -07:00
Cory Rivera
34d36c1de1 Prompt for Python installation after choosing a Jupyter kernel in notebook (#4453) 2019-03-13 18:44:54 -07:00
Chris LaFreniere
cca84e6455 Fix disappearing notebook table (#4466) 2019-03-13 18:32:31 -07:00
Matt Irvine
82ce1ace28 Put back code to refresh tree when capabilities provider gets new capabilities (#4475) 2019-03-13 17:41:29 -07:00
Anthony Dresser
e59d5a766f Enable similarity and locker (#4435)
* turn on similarity

* turn on locker
2019-03-13 16:51:01 -07:00
Anthony Dresser
98a8103f5a fix spacing in yml (#4436) 2019-03-13 16:49:26 -07:00
Alan Ren
5faf2d9cb2 bump up the extension version for new release (#4456)
* bump up the extension version for new release

* change url for dacpac ext
2019-03-13 16:01:28 -07:00
Alan Ren
81a8593eb6 bump up the extension version for new release (#4456)
* bump up the extension version for new release

* change url for dacpac ext
2019-03-13 15:46:03 -07:00
Anthony Dresser
b6584c9ddf Change shutdown listeners (#4282)
* change shutdown to use proper notification

* change to use storage service

* remove unused imports

* fix test

* change shutdown methods to private

* remove unusde imports

* fix tests

* formatting
2019-03-13 15:15:51 -07:00
Raj
08d4cc9690 #4441:Remove notebook editor - don't save selected (#4449) 2019-03-13 14:25:45 -07:00
kisantia
0565162fde remove broken link from dacpac extension readme (#4448) 2019-03-13 14:03:32 -07:00
Charles Gagnon
31614247cf #3127 #478 Fix 2 Edit Data grid issues (#4429)
* 2 fixes :

1. Fix it so that edits made to a table with a single column will correctly create a new row when done editing. This is done by caching whether the cell is dirty in on the onCellEditEnd callback and then when onCellSelect is called to switch cells we only return early if the cell isn't dirty. Before we were returning early and thus not going into any of the code that creates the new row (submitCurrentCellChange)

2. Fix it so we don't throw an error when deleting the NULL (new) row. As noted in the code this should really be handled by not displaying the context menu to begin with for that row but that's a bit more involved of a fix so for now I'm at least making it not display an error to the user - it'll just do nothing.

Manual testing for now - I tried to add tests but the core logic and the UI layer are too intertwined so this will likely need to be a full end-to-end UI test. I'll continue working on adding some for this dialog but for now I'd like to at least submit these fixes since they're pretty painful to deal with.

* Undo changes to addRow

* Clean up resetCurrentCell and add comment to setCurrentCell

* Use reset method instead of directly initializing currentCell

* Add issue # to comment
2019-03-13 13:52:35 -07:00
Karl Burtram
e9390dcd48 Update "Preview features" notification text (#4444) 2019-03-13 13:50:42 -07:00
Gene Lee
c9b3e2b156 Added 'serverMajorVersion' key to context which is missed currently and caused failure for loading 'Create External Table' menu (#4423) 2019-03-13 13:32:04 -07:00
Anthony Dresser
ace6012c1c Grid scrolling bugs (#4396)
* better maintense of heights in scrollable splitview

* formatting

* fix issue around views resizing messing with render logic

* remove commented code
2019-03-13 11:51:47 -07:00
Chris LaFreniere
17901fbf3d Fix Issue when OE connection Disconnects on Notebook Close (#4425)
* Fix OE connection closing when notebook closes

* handle connections created through Add new connection
2019-03-13 11:32:12 -07:00
udeeshagautam
2c7b5578e7 Bug/3731 results scroll (#4408)
* Bug 3731: Minor issues saving scroll position in results

Fixing the second part i.e. scroll position of results view while switching tabs. The resize call was not respecting the old scrolbar state. Making an explit call to set scroll position  to ensure this sets at the end.
2019-03-13 11:03:41 -07:00
Chris LaFreniere
b2b7d18802 Change Kernels Dropdown to show Switching instead of Loading On Kernel Change (#4426)
Change Kernels Dropdown to show Changing instead of Loading On Kernel Change
2019-03-13 09:59:19 -07:00
Geoff Young
965da0535a Fix sqlDropColumn description (#4422) 2019-03-13 01:06:16 -07:00
Raj
ebd187ec06 #4363: Reopen notebook editors when ADS launched (#4424)
* #4363: Reopen notebook editors when ADS launched

* Code review changes
2019-03-12 23:02:37 -07:00
Kevin Cunnane
b495fb7a37 Add notebook file icon support (#4419)
- Added to both built-in themes. Long term would be good to contribute this back to Seti so it works without a carbon edit tag.
- Issue #4418 tracks remaining problem where for new notebooks it's not set initially. This is blocked by Raj's work so will update once that lands.
2019-03-12 21:23:43 -07:00
David Shiflet
58e5125cde Add scripted object name to query editor tab display (#4403)
* Add scripted object name to query editor tab display

* Update src/sql/parts/query/common/queryInput.ts

Co-Authored-By: shueybubbles <shueybubbles@hotmail.com>
2019-03-12 22:07:11 -04:00
Anthony Dresser
dadfbd2ddb add check to remove errors (#4412) 2019-03-12 15:32:41 -07:00
Charles Gagnon
9fdeec6128 #3224 Fix extra connections populating MRU List (#4368)
* Modify where we add active connections so that we can use the saveTheConnection option to decide whether to add a connection to the MRU. This was necessary because the old location was called from onConnectionComplete which is sent by the SqlToolsService - and that doesn't get any UI related information like the options. The new location is still only called after the connection completes and will be added only if the connection succeeds.

Added new test and updated existing tests to handle new logic (plus a bit of async-refactoring).

* Fix couple spacing issues

* Add logic back in to short-circuit if we already have the connection in the active connections list.

* Fix spaces -> tabs
2019-03-12 14:05:50 -07:00
Matt Irvine
e783aeab66 Use max column width when auto-sizing columns (#4394) 2019-03-12 14:03:37 -07:00
Karl Burtram
53a94cc7bb Revert SQL Tools Service to 1.5.0-alpha.71 (#4413) 2019-03-12 13:38:44 -07:00
Anthony Dresser
839a9b6cb8 move event to better understand when things are happening (#4393) 2019-03-12 13:19:08 -07:00
Anthony Dresser
2557d77ae3 readd row height; add font styles to message panel as well (#4388) 2019-03-12 13:18:25 -07:00
Raj
6a7df2f1ae Adding back save api (#4407)
* #4339: Kernel change event occurs after model load

* #4347: Code cleanup - Notebooks Save

* Remove save method from sqlops

* Adding save method to api's

* Adding save method to ext host

* Misc change
2019-03-12 13:07:10 -07:00
Maddy
2db83b3892 Added localizie for the warning string (#4411) 2019-03-12 13:06:16 -07:00
Yurong He
08c7cc0918 Fixed #4384 add await on disconnect (#4389)
* Fixed #4384 add await on disconnect

* Resolve PR comment
2019-03-12 13:06:02 -07:00
Kevin Cunnane
d555dcb6d7 Fix minor error in snippet (#4398)
- Found a snippet missing a `,`
2019-03-12 12:14:24 -07:00
Kevin Cunnane
7226f25c67 Fix #4356 New Notebook from connection doesn't connect (#4364)
* Fix #4356 New Notebook from connection doesn't connect
Fix new notebook error by passing profile instead of ID.
- I could've just sent the ID over, but this fix sets the stage for disconnected connections to work (since we have enough info to properly connect).
- There's a bug in NotebookModel blocking the disconnected connection part working, but Yurong's in progress fixes will unblock this. Hence checking in as-is and working to properly unblock once that's in.

* Support connection profile in commandline service
- Added new context API for things that want to work on commandline and object explorer
- Refactored commandlineservice slightly to be async & have a simpler execution flow (far fewer if/else statements)

* Fix unit tests
- Fixed 2 issues raised by tests (sholdn't do new query if no profile passed, shouldn't error on new query failing)
- Updated unit tests to pass as expected given changes to the APIs.
2019-03-12 12:14:08 -07:00
Maddy
77a3be6fd7 pulling max bytes of data through the webhdfs api (#4314)
* pulling max bytes of data through the webhdfs api

* Added warning message for the Users to inform the data truncation.

* Updated the warning message on the notification flyer.
2019-03-12 10:38:34 -07:00
Raj
2397df7f22 #4339: Kernel change event occurs after model load (#4366) 2019-03-12 08:21:00 -07:00
Yurong He
118d2c7273 Fix #4047 Redesign notebook model to handle single client session (#4371)
* Start single client session based on the default kernel or saved kernel in NB.

* Added kernel displayName to standardKernel.
Modified name to allign wtih Juptyer Kernel.name.
So we can show the displayName during startup and use the name to start the session.

* Change session.OnSessionReady event in KernelDropDown

* Added model.KernelChnaged for switching kernel in the same provider

* Fixed session.Ready sequence

* Fixed merge issues

* Solve merged issue

* Fixed wrong kernel name in saved NB

* Added new event in Model to notify kernel change.
Toolbar depends on ModelReady to load

* Change attachTo to wait for ModelReady like KenelDropDown

* sanitizeSavedKernelInfo to fix invalid kernel and display_name. For example: PySpark1111 and PySpark 1111


* Added _contextsChangingEmitter to change loadContext msg when changing kernel

* Resolve PR comments
2019-03-11 17:59:13 -07:00
David Shiflet
b44d2b1bb3 Re-enabled command line service tests (#4387) 2019-03-11 19:31:11 -04:00
Chris LaFreniere
9867d88067 check for changeRef not destroyed before detecting changes (#4385) 2019-03-11 14:23:37 -07:00
Chris LaFreniere
037c49e2c6 Warning for table max rows displayed (#4357)
* Warning for top rows

* change single to double quotes when calling localize method
2019-03-08 19:01:21 -08:00
Chris LaFreniere
1e989060f9 Rewrite Spark UI link when using unified connection (#4362)
* Rewrite Spark UI link when using unified connection

* Add more robust error checking
2019-03-08 17:34:47 -08:00
Raj
4d6271c161 'Confirm save' implementation while closing untitled/existing notebooks (#4349)
* #4326: 'Confirm save' while closing both notebook

* Adding comment
2019-03-08 13:28:15 -08:00
Kevin Cunnane
c3900f6984 Notebooks: fix AttachTo showed only Localhost (#4354)
The Attach To was showing only localhost for SQL, since we overrode the standard kernels from SQL with the ones from Jupyter.
Fix is to save all standard kernels.
Also, added dispose handling for some events I found during debugging and removed unused imports
2019-03-08 13:27:14 -08:00
Gene Lee
aa1a036f66 Fixed bug: tree in extension does not show icon (#4348) 2019-03-08 12:34:13 -08:00
Karl Burtram
26274e6c5d Fix connection dialog Saved Connections refresh timing (#4346) 2019-03-08 11:45:11 -08:00
kisantia
bcfbe5a284 fix flatfile and dacfx wizard not defaulting to selected connection when launched from command palette (#4344) 2019-03-08 09:19:03 -08:00
Charles Gagnon
496243fbc7 Fix extra spacing in the file search view (#4343)
Recent changes in the VS Code layout for that viewlet caused the min-height property to affect the display (the property was set on that class before but the layout prevented it from actually being displayed as it was).
I removed the style for the messages class completely since I couldn't find a place that we actually used that ourselves - and anyways having styling on such a common name like messages isn't really a good practice since it applies to everything in ADS.
2019-03-08 07:32:04 -08:00
Raj
036ffe595a #3920: Notebooks file save/save all/cache - for existing files (#4286)
* #3920: Notebooks file save

* Missed in merge

* #4290: Untitled save and native dirty implementation

* Misc changes

* Content Manager, notebooks extension and commented failed unit tests

* Removing modelLoaded event
2019-03-07 18:07:20 -08:00
Maddy
2a903e9f03 handle non ascii characters hdfs filename (#4340)
* encoding the url so that special characters doesn't make the rquest a bad request.
2019-03-07 16:21:03 -08:00
Gene Lee
36e5bbb752 added 'fireOnTextChange' field to azdata.proposed.d.ts (#4341) 2019-03-07 16:03:50 -08:00
Anthony Dresser
96a976d826 add new release yml (#4333) 2019-03-07 15:33:13 -08:00
Kevin Cunnane
ff514a0568 Remove Analyze in Notebook from command palette (#4330) 2019-03-07 14:26:42 -08:00
Kevin Cunnane
a4d99b78d5 cluster deploy extension: Add localization support and fix " to ' strings (#4332)
* Add localization support and fix " to ' strings

* Fix ${ usage
2019-03-07 14:26:31 -08:00
Gene Lee
029c69ecd3 Fixed issue: input change on dropdownbox not reflected to 'dropdownbox.… (#4316) 2019-03-07 13:35:10 -08:00
Alan Ren
9e1f04e476 Enforce vscode and ads version check when installing extensions (#4267)
* engine check when install extension

* gallery install/update and vsix install

* FIX COMMENTS

* Fix the detail not loading issue when version is invalid

* add more comments and adress PR comments

* add install telemetry for install from vsix scenario

* correct the name of the version property for telemetry
2019-03-07 13:04:50 -08:00
Aditya Bist
c8bde41451 Disable edit step until all steps are loaded (#4327)
* disable edit step until all steps are loaded

* job check
2019-03-07 12:58:58 -08:00
Maddy
e16c01623d Added the new hdfs icon for the web HDFS folder. (#4317)
* Added the new hdfs icon for the web HDFS folder.

* overriding the getNodeInfo() in the ConnectionNode
2019-03-07 00:57:12 -08:00
Anthony Dresser
7de294a58e change sizing behavior to allow the messages to fulling collapse down (set results to have no max height) (#4313) 2019-03-06 22:44:49 -08:00
Alan Ren
060343f096 fix couple build issue due to merge issue (#4324)
* fix the build error on linux and mac

* one more fix
2019-03-06 21:53:09 -08:00
Alan Ren
addba0d007 remove the modelviewdialog namespace from azdata (#4301) 2019-03-06 21:32:05 -08:00
Alan Ren
68418f2c8f update target environment type page based on latest design (#4311) 2019-03-06 21:21:47 -08:00
Karl Burtram
428dd17d54 Set dashboard DB to master only for MSSQL provider (#4321) 2019-03-06 19:40:46 -08:00
Matt Irvine
7344b41f47 Fix bug where git extension fails in packaged builds (#4318) 2019-03-06 18:56:04 -08:00
kisantia
5f003b0dd7 Move DacFx wizard into separate extension (#4115)
* Moved dacfx wizard into separate extension

* updating to use azdata

* one more azdata change

* bump import extension version

* renaming extension to dacpac
2019-03-06 17:45:30 -08:00
Kevin Cunnane
b8f454b8ac Add request dependency to correct package.json (#4306)
- This was needed in mssql extension, not the main package.json
2019-03-06 14:33:07 -08:00
Anthony Dresser
b45e03a45a enable classifier (#4296) 2019-03-05 23:49:58 -08:00
Anup N. Kamath
0a268f35bc Fix backup (#4274)
* check to see whether options is available

* removing options state and using _modelOptions

* removed additional space

* making options getter private as not intended to expose
2019-03-05 19:17:42 -08:00
Chris LaFreniere
e3709533b4 Add New Notebook to File Menu (#4287) 2019-03-05 17:42:35 -08:00
Gene Lee
acc8d5f7b2 Added request dependency in mssql extension (#4297) 2019-03-05 17:33:28 -08:00
Anthony Dresser
da06a96630 Add Data Explorer Context and apply to disconnect (#4265)
* adding context

* apply extension changes

* shimming disconnect

* add data explorer context menu and add disconnect to it

* clean up shim code; better handle errors

* remove tpromise

* simplify code

* add node context on data explorer

* formatting

* fix various errors with how the context menus work
2019-03-05 17:09:00 -08:00
Yurong He
7eaf8cfd2f Add check OE node tests (#4273)
* Added verify OE child nodes tests for sandalone and BDC instance

* msg changes

* Added standalone OE node test

* Resolved PR comments

* Change env name

* Added scripts to set env for integration test
2019-03-05 14:42:05 -08:00
Cory Rivera
5248c8f78d Convert caught error to string in notebook onLoad error message. (#4276) 2019-03-04 16:49:23 -08:00
Gene Lee
f4365dbd3a Added WebHDFS rewritten to provide correct Error object and localized error messages (#4223) 2019-03-04 15:23:50 -08:00
Karl Burtram
2309b16bd4 Remove watch script and use 'yarn watch' instead (#4277) 2019-03-04 13:47:31 -08:00
Karl Burtram
c65af61a68 Bump ADS to 1.5.1 2019-03-04 13:01:37 -08:00
Yurong He
a48e9bc64c Fixed #4206 and #4207 open and close notebook quickly issue #4240 (#4255)
* Fixed  #4206 and #4207

* Check if it makes my PR run tests

* Add isReady to JupyterSessionManager
2019-03-04 12:46:27 -08:00
Karl Burtram
b4984d7f2d Update 'sqlops' to 'azdata' in Notebook Manager (#4275) 2019-03-04 12:45:34 -08:00
Yurong He
1017d62f0d Move sql related code to sqlNotebook folder (#4254)
* Move sql related code to sqlNotebook folder

* Resolve PR comments: rename folder to sql.

* Fixed the import path after rename folder
2019-03-04 09:45:32 -08:00
Yurong He
ebc208cacd Fixed #4181 and #4167 change kernel issue between SQL and Sparks #4238 (#4256)
* Fixed #4181 and #4167

The problems are:
- When change Kernel, setProviderIdForKernel switches Kernel first. So when we switch kernel across provider for exmple from PySpark3 to SQL. The Kernel is set SQL already in ClientSession.changeKernel. Then we lost oldKernel info.
  The fix is cache the old session in model before switch and use it to get the correct context
- SQL Kenerl could make mulitple connects from "Add new connection". While we didn't track them, those connections didn't close properly when close the notebook
  The fix is saving the connections made from "Add new connection" in model. and close them and activeConnection when close notebook

Problem is not solved yet in this PR:
- Didn't shutdown Jupytper when swich kernel from spark kernel to SQL.
2019-03-01 22:11:45 -08:00
Anthony Dresser
0236c8e7f8 Data Explorer Disconnect and Error Handling (#4243)
* adding context

* apply extension changes

* shimming disconnect

* add data explorer context menu and add disconnect to it

* clean up shim code; better handle errors

* remove tpromise

* simplify code
2019-03-01 17:47:28 -08:00
Cory Rivera
db8a92f5c2 Update LabeledMenuItemActionItem to match new vscode behavior. (#4264) 2019-03-01 17:37:12 -08:00
Charles Gagnon
c1e5408492 Change vscode folder name to azuredatastudio 2019-03-01 14:32:42 -08:00
Karl Burtram
84890eb1b4 Update product references from 'sqlops' to 'azdata' (#4259)
* Update extensions to use azdata

* Switch core code to use azdata
2019-03-01 13:59:37 -08:00
Alan Ren
220685a522 fix the undefined error when uninstalling extension (#4258) 2019-03-01 13:58:00 -08:00
Karl Burtram
8ebf5dbcb4 Add azdata.d.ts for new extensibility APIs (#4247)
* Add azdata.d.ts for new extensibility APIs

* Update azdata typing files for connection API proposal

* Add implementation for azdata module

* Fix build break in agent
2019-03-01 11:58:32 -08:00
Alan Ren
dad807d62d select cluster page and status update for tool when installing (#4251) 2019-03-01 11:12:57 -08:00
Karl Burtram
8e52ffa30e Fix copywrite headers in notebook extension (#4253) 2019-03-01 10:34:26 -08:00
Raj
18970ff0b9 #4225: Markdown content disappears when edit (#4249) 2019-02-28 19:18:40 -08:00
Cory Rivera
630698459b Update output channel name for Jupyter Notebooks. (#4246) 2019-02-28 16:45:56 -08:00
Karl Burtram
f8e854a087 Turn-on auto-size columns by default (#4241) 2019-02-28 15:24:38 -08:00
Karl Burtram
3b2274b0aa Update Azure resource explorer section title (#4237) 2019-02-28 15:22:40 -08:00
Ronald Quan
0d1ebce1a1 Ron/bdc script (#4221)
* WIP adding scripting support.

* Adding deploy command along with additional env vars needed.

* Adding script generation that sets envars, kube context, and mssqlctl

* Adding test email for docker email envar until we update UI.

* Adding cluster platform detection and disabling generate script after first click.

* Fix spacing and adding comment.
2019-02-28 14:26:50 -08:00
Alan Ren
70d86ce9a2 bump the version of import extension for a new package (#4244) 2019-02-28 13:41:01 -08:00
Cory Rivera
291f591af3 Use upper case PATH for jupyter environment variables. (#4222) 2019-02-27 14:21:34 -08:00
Cory Rivera
5a48c52a95 Delete duplicate path variables when setting up Jupyter environment config. Also added additional error message info on jupyter start. (#4212) 2019-02-27 13:30:27 -08:00
Raj
5625ef956d mkdir under notebook extension folder (#4214) 2019-02-27 13:29:01 -08:00
PaulRandal
969733ab77 Added VDI_CLIENT_OTHER to the list of ignored waits (#4197)
* Update waits_paul_randal.sql

Added the PREEMPTIVE_OS_FLUSHFILEBUFFERS wait to the list to ignore

* Update waits_detail_paul_randal.sql

Add PREEMPTIVE_OS_FLUSHFILEBUFFERS to ignore list.

* Update waits_paul_randal.sql

* Update waits_detail_paul_randal.sql

* Update package.json

* Update README.md

* Update CHANGELOG.md
2019-02-27 09:07:41 -08:00
Cory Rivera
12a1ac1a7d Remove leftover merge tags from windows integration test script. (#4213) 2019-02-26 18:02:13 -08:00
Chris LaFreniere
4da322a03f Stop cell content from moving around on hover (#4202) 2019-02-26 17:01:20 -08:00
Anthony Dresser
d5754c00e2 Add bot configs to enable bot features (#4209)
* add bot configs to enable bot features

* update classifier label strings

* initial check in should perform be false to double ensure things are working properly
2019-02-26 16:23:48 -08:00
Anthony Dresser
2e9b5f3a2b Fixes azure sql expansion (#4185)
* fixes azure sql expansion

* remove unneeded changes

* remove unused code
2019-02-26 15:29:02 -08:00
Alan Ren
b11a8e9c0c add placeholder for container username/password input box (#4210)
* add placeholder for container username/password input box

* spacing
2019-02-26 15:19:36 -08:00
Karl Burtram
e37533afbb Add null check to extensionIdentifier to show reload notification (#4208) 2019-02-26 14:18:05 -08:00
Karl Burtram
4a476673ac Update SQL Tools Service to 1.5.0-alpha.73
Update SQL Tools Service to 1.5.0-alpha.73 to pickup the managed batch parser assembly.
2019-02-26 13:35:50 -08:00
Raj
fe5386cc08 display_name undefined error in javascript (#4187) 2019-02-26 13:10:40 -08:00
Alan Ren
8bfb1a9d39 add restore default values button for ports and container settings (#4195)
* add restore default values button for ports and container settings

* change some resource strings
2019-02-26 12:48:35 -08:00
Kevin Cunnane
109aafcbc0 Update vscode-nls in notebook and samples, plus fix samples compilation (#4203)
- Upate vscode-nls to 4.0.0 in notebook extension. Should be fix for Insiders build failure due to localization package failing
- Updated samples to remove as vscode-nls if not needed, or update if still needed
- Updated samples using `npm audit fix`
- Fixed compile errors in all the samples
2019-02-26 12:45:45 -08:00
Karl Burtram
e289c06d8d Add no-op debug extensibility APIs (follow-up) (#4192)
* Add no-op debug extensibility APIs

* Remove unneeded SQL EDIT tags
2019-02-26 08:51:55 -08:00
Karl Burtram
78c1c318c5 Add no-op debug extensibility APIs (#4188) 2019-02-26 08:47:10 -08:00
Matt Irvine
07983d75ea Use correct new line character when copying query results (#4170) 2019-02-25 16:39:57 -08:00
Ronald Quan
d0a4a4242d Feature/mssql-big-data-cluster (#4107)
* Adding kubernetes installer.

* Adding variety of kubectl support and integrating into the kubeconfig target cluster page.

* Addressing PR comments, refactored utility file locations and added missing license headers.
2019-02-25 15:09:22 -08:00
Alan Ren
a71be2b193 Alanren/bdc (#4161)
* wip

* target cluster type page

* finish target cluster type page

* remove commented line
2019-02-25 14:04:12 -08:00
Anthony Dresser
779ca13d48 remove builder references from panel (#4149) 2019-02-25 12:43:00 -08:00
Anthony Dresser
f3b0a50db7 remove builder from button (#4146) 2019-02-25 12:42:33 -08:00
Matt Irvine
c831596e02 Fix Windows issues with menu, packaging, and test script (#4144) 2019-02-25 11:06:31 -08:00
Kevin Cunnane
2ae369fbdb Notebook fixes: Fix #4129, fix #4116, Fix #3913, fix empty results error (#4150)
- Fixes #4129 Overlapping command help windows in notebook
  - Do not show parameter hints for inactive cells, to avoid them hanging around when no longer selected
- Fixes #4116 Notebooks: Intellisense Doesn't Work using Add New Connection
  - Move connect/disconnect logic to 1 place (code component) instead of 2
  - Handle the case where you connect after choosing active cell. We now hook to the event and update connection
- Fix issues in sql session manager where result outputs 0 rows. This was failing to show the empty resultset contents, which is a regression vs. query editor. It also put unhandled error on the debug console
- Fix #3913 Notebook: words selected in other cells should be unselected on cell change

Note: after fix, now looks as follows. Need to do follow up to get correct grid min height

![image](https://user-images.githubusercontent.com/10819925/53280226-9e629580-36cc-11e9-8f40-59cd913caeee.png)
2019-02-25 10:52:07 -08:00
Aditya Bist
f2c9d968a4 fix Object explorer tests (#4135) 2019-02-25 09:51:43 -08:00
Raj
c3f02980a0 Fix #3734 - Codecell content disappers when tabbing editors (#4153) 2019-02-24 19:31:42 -08:00
Kevin Cunnane
7d5ce7b5d7 Fix #4145 Possible for loading icon to appear with rendered widget (#4147)
- For cached insights, it was going down the checkStorage path which wasn't covered
2019-02-22 18:06:00 -08:00
Cory Rivera
8bb71eeb51 Fix lingering bugs from notebook code merge. (#4143)
* Add request to notebook dependencies.
* Use offline python package for windows installation.
2019-02-22 17:31:24 -08:00
Kevin Cunnane
5a88598811 Fix #3778 intellisense is delayed (#4134)
- Jupyter completion item support was awaiting info before responding. Fix is to check if this is even a notebook cell first, then only await stuff if that's true
2019-02-22 16:22:40 -08:00
Raj
da3fbd386d #4132 fix for disolayError (#4133) 2019-02-22 16:00:59 -08:00
Chris LaFreniere
1e915aad20 Make "Double-click to edit" in empty md cell a bit nicer looking (#4102) 2019-02-22 16:00:35 -08:00
Kevin Cunnane
889d5e5b28 Add loading spinner for insight widgets while they're in a loading state (#4136)
- This was very confusing without status indicator, is it complete or in progress?

Please let me know if you see issues with this e.g. was there a reason we didn't do this up to now?

Initial state:

![image](https://user-images.githubusercontent.com/10819925/52883300-4e5d5f00-311f-11e9-988c-f7a70dc0a899.png)

On loading / error:
![image](https://user-images.githubusercontent.com/10819925/52883203-faeb1100-311e-11e9-9757-13a5fd4104c6.png)
2019-02-22 16:00:06 -08:00
Matt Irvine
51cf2df2f8 Reapply changes to publish.ts script (#4138) 2019-02-22 15:52:10 -08:00
Matt Irvine
e690285d9d Undo accidental merge commits (#4137) 2019-02-22 14:52:43 -08:00
Raj Musuku
81d6423f24 Merge branch 'master' of https://github.com/Microsoft/azuredatastudio 2019-02-22 12:58:25 -08:00
Alan Ren
046dee7389 add link area support for text component (#4103)
* add link area support for text component

* add comment for localizable resources

* address comments
2019-02-22 12:53:09 -08:00
Raj Musuku
a33a24dddf Merge branch 'master' of https://github.com/Microsoft/azuredatastudio 2019-02-22 08:45:17 -08:00
Anthony Dresser
636bdbd12c copycat bot yml (#4125) 2019-02-21 22:51:13 -08:00
Raj Musuku
0ab3492afd Merge from master 2019-02-21 18:07:18 -08:00
Raj Musuku
666ae11639 Merge from master 2019-02-21 17:56:04 -08:00
Matt Irvine
826856c390 Merge VS Code 1.30.1 (#4092) 2019-02-21 17:17:23 -08:00
Chris LaFreniere
a764a481f3 Ensure that we preserve rest of PATH when starting Jupyter (#4109) 2019-02-21 11:54:08 -10:00
Anthony Dresser
e345090015 Data Explorer Sourcing (#4033)
* added initial data explorer viewlet

* added dataexplorer contribution point

* removed test view

* remove unused imports

* inital data source, needs work

* add shim for ext host

* formatting

* making the necessary changes to use OE for tree view; need to look at TreeUpdateUtils.connectAndCreateOeSession

* formatting

* shimming oe more

* update to add correct context

* working cross provider; need to fix connection

* connection works but it adds the connection to the oe for some reason

* formatting

* add custom connection dialog code path

* hashing between trees

* added flag and tests

* add id maps to handle multiple nodepaths

* add necessary car edit parts

* keep current behavior in prodc

* fix tests

* address comments

* update comments to be more informative

* finish merge

* update comments

* fix whitespace
2019-02-21 13:47:59 -08:00
Aditya Bist
cc97198fe4 Agent improvements and fixes (#4077)
* fixed new/edit job break when no start step given

* bump agent version

* agent version bump
2019-02-20 15:56:54 -08:00
Aditya Bist
5a146e34fa fixed scrolling for connection viewlet (#4073)
* fixed scrolling for connection viewlet

* removed horizontal scrolling
2019-02-20 13:51:56 -08:00
Cory Rivera
70838c3e24 Move SQL 2019 extension's notebook code into Azure Data Studio (#4090) 2019-02-20 10:55:49 -08:00
Chris LaFreniere
2dd71cbe26 Change SQL kernel to check queryManagementService instead of hardcoding (#4098)
* Change SQL kernel to check queryManagementService instead of hardcoding

* addressing PR comments
2019-02-19 15:55:11 -10:00
Chris LaFreniere
32c013a72c Add total execution time message for SQL notebooks (#4093)
* Display total execution time for sql notebooks

* remove handlebatchstart since it was unnecessary
2019-02-19 15:43:16 -10:00
Chris LaFreniere
db6e1ae558 Merge branch 'master' of https://github.com/microsoft/azuredatastudio 2019-02-19 17:38:10 -08:00
Chris LaFreniere
4117da6e93 undo remove sql kernel setting 2019-02-19 17:38:00 -08:00
Chris LaFreniere
02b1ba03ed remove sql kernel setting 2019-02-19 17:35:33 -08:00
Kevin Cunnane
1f501f4553 Improve cell language detection and add support for language magics (#4081)
* Move to using notebook language by default, with override in cell
* Update cell language on kernel change
* Tweak language logic so that it prefers code mirror mode, then falls back since this was failing some notebooks
* Add new package.json contribution to define language magics. These result in cell language changing. Language is cleared out on removing the language magic
* Added support for executing Python, R and Java in the SQL Kernel to prove this out. It converts to the sp_execute_external_script format

TODO in future PR:

* Need to hook up completion item support for magics (issue #4078)
* Should add indicator at the bottom of a cell when an alternate language has been detected (issue #4079)
* On executing Python, R or Java, should add some output showing the generated code (issue #4080)
2019-02-19 17:05:56 -08:00
Chris LaFreniere
0205d0afb5 Change default max table rows returned in notebook to 5000, make it user configurable (#4084) 2019-02-19 15:01:47 -10:00
Anthony Dresser
ccf9bf4613 change rendering in panel to fix event handelrs (#4082) 2019-02-19 12:48:07 -08:00
Anthony Dresser
d4704e39ac Another code layering (#4037)
* working on formatting

* fixed basic lint errors; starting moving things to their appropriate location

* formatting

* update tslint to match the version of vscode we have

* remove unused code

* work in progress fixing layering

* formatting

* moved connection management service to platform

* formatting

* add missing file

* moving more servies

* formatting

* moving more services

* formatting

* wip

* moving more services

* formatting

* move css file

* add missing svgs

* moved the rest of services

* formatting

* changing around some references

* formatting

* revert tslint

* revert some changes that brake things

* formatting

* fix tests

* fix testzx

* fix tests

* fix tests

* fix compile issue
2019-02-19 12:11:54 -08:00
Chris LaFreniere
4a82abc19b Notebooks: Greatly Reduce Time to Generate HTML Table String (#4086)
* Greatly reduce time to generate html table string

* change outer tag to table instead of html

* address PR feedback for more descriptive variable name
2019-02-19 09:03:58 -10:00
Chris LaFreniere
3ae32ab0a0 Fix the Attempt to use a destroyed view Errors (#4087) 2019-02-19 08:28:55 -10:00
Alan Ren
1cc6a108a7 Deprecate the modelviewdialog namespace (#4075)
* Deprecate the modelviewdialog namespace

* use @deprecated tag
2019-02-19 09:43:37 -08:00
Chris LaFreniere
d4ffe53dbd Add database name to attach to (if not connected to master) (#4076) 2019-02-15 16:50:14 -10:00
Yurong He
f43b3508e9 Added SQL notebook IntelliSense (#4064)
* Added SQL notebook intelliSense

* Resolved PR comments.

* catch disconnect error
2019-02-15 15:53:06 -08:00
Chris LaFreniere
ea0c326d3d Allow code coverage command to succeed again (#4054) 2019-02-15 12:07:52 -10:00
Kevin Cunnane
4843480fbf Update server reports extension version, fix its build breaks, and reduce its size to 86Kb (#4062)
* Updated version
* On building found it had build break due to unused imports. Turns out none of the code is used (it's just a package.json + SQL file extension) so removed it all
* Removed all unnecessary node module imports, reducing size from 5.4MB to 86KB. We should probably do this for all extensions
2019-02-15 10:33:22 -08:00
Chris LaFreniere
930e14e258 Add bottom margin to notebook table, fix python highlighting (#4055) 2019-02-15 08:32:27 -10:00
David Shiflet
87bbb41fb6 window reuse for connections (#4049)
* window reuse for connections

* space after colon

* use undefined instead of null
2019-02-15 09:44:06 -05:00
Kevin Cunnane
e767f68f89 Move New Notebook to the connection node in MSSQL server OE connections (#4053) 2019-02-14 15:47:36 -10:00
Raj
b4d304c21e 'Attach to' with Spark kernel resets to sql connection on cancelling connection dialog (#4024)
* Sql connection resets to Select Connection on cancelling dialog

* Hiding error message wehen cancel the connection dialog
2019-02-14 16:39:23 -08:00
Chris LaFreniere
db1f412dae show errors and messages in output (#4031) 2019-02-13 14:54:51 -10:00
PaulRandal
a73f5e83ec Add PREEMPTIVE_OS_FLUSHFILEBUFFERS to ignore list in waits script (#4030)
* Update waits_paul_randal.sql

Added the PREEMPTIVE_OS_FLUSHFILEBUFFERS wait to the list to ignore

* Update waits_detail_paul_randal.sql

Add PREEMPTIVE_OS_FLUSHFILEBUFFERS to ignore list.
2019-02-13 13:21:17 -08:00
Karl Burtram
49b2e98a8f Update readme and changelog for Feb release (#4025) 2019-02-13 09:33:40 -08:00
Alan Ren
b3a16fd0ce Feature/bdc create (#4012)
* initial checkin

* rename

* wizard pages

* target cluster radio button group

* resource strings

* existing cluster picker

* revert changes to unwanted file

* revert unwanted changes-2

* update cluster icon

* settings page

* fix group container

* hyperlink component

* address review comments

* comments part 2
2019-02-12 22:13:30 -08:00
Karl Burtram
dd6735ec04 Bump Azure Data Studio to 1.5.0 2019-02-12 21:10:55 -08:00
Chris LaFreniere
9ebf1436d2 Ensure we always switch to a kernel that exists in the session manager (#4015)
* Ensure we always switch to a kernel that exists in the session manager

* PR feedback, create new helper method
2019-02-12 12:46:58 -10:00
Kevin Cunnane
0aa71b5237 Fix kernel name check bug, double-event hooking, and other Notebook issues (#4016)
* Fix error where kernel name was compared to itself. This doesn't break anything right now since we happen to have special handling of Python3, and for other kernels they share the same set of supported providers (which is what the check is used for). However it needs fixing for next release.
* Fix console error due to queryTextEditor trying to access model before it's ready
* Fix issues where notebook model hooked to session events multiple times
* Removed calls that weren't needed such as loadActiveContexts (if undefined, does nothing) and passing connection to initialize method
2019-02-12 14:26:22 -08:00
Alan Ren
7ef2d52efd add admin pack to recommended ext list (#4019) 2019-02-12 13:00:31 -08:00
Karl Burtram
a5c6dfe62b Bump agent and import extension versions (#4018) 2019-02-12 12:53:52 -08:00
Alan Ren
4a606e0cb2 Alanren/admin pack (#4014)
* admin pack

* formatting and typo fixes

* remove changelog.md
2019-02-12 12:04:19 -08:00
Chris LaFreniere
27370c655d fix left table border to be dotted, no longer have table border on div (#4010) 2019-02-12 08:49:44 -10:00
Alan Ren
887f4e8985 Alanren/fix4001 (#4011)
* fix for 4001

* Revert "fix for 4001"

This reverts commit 91fed44f063acb44b844a206a13e4074150d8118.

* fix for issue 4001
2019-02-11 21:51:55 -08:00
Matt Irvine
c91c4b01f9 Fix bug minimizing a maximized result grid (#4007) 2019-02-11 21:51:06 -08:00
Yurong He
5f198dba08 Added hard coded pySpark3 kernel for analyze notebook. Good to know and fix it in time. (#4009) 2019-02-11 17:21:08 -08:00
Kevin Cunnane
67f9a7f5e4 Fix issues due to missing notebook values (specs and cells) (#4008)
- Fix #3844
    - Fix #3955
    - Specs can be null on early load of Jupyter kernels
    - Cells were missing in some reference test .ipynb files. We should be resilient to malformed files if possible.
2019-02-11 17:17:56 -08:00
Yurong He
62404721ed Fixed #3954 pass connection info to new notebook flow (#4000)
* Fixed #3954 
The problem is: connectionProfileId is not passed into New Notebook flow.
The fix is: plumbing connectionProfileId via NotebookInput.

* Resolved PR comments
2019-02-11 15:28:05 -08:00
Kevin Cunnane
6d37329e74 Fix #3989 notebook execution count should start empty (#4004)
- Fixed issues where we missed using actual execution count / starting from empty on this.
2019-02-11 15:18:54 -08:00
Karl Burtram
0c316d3225 Bump Azure Data Studio to 1.4.5 2019-02-11 09:17:37 -08:00
Kevin Cunnane
131644477d Beginning of fix for notebook perf (#3984)
Fixes #3843. Now includes full fix which limits length and ensures a scrollbar is available

- Set max size for editor. 4000px gets us 200-250 lines before needing a scrollbar. 
- Adds layout updating which should also ensure accurage line highlighting to the right of the editor. What's happening is initial size is slightly off, so need to layout a 2nd time (e.g. layout once, let flex figure things out, then layout a 2nd time). This isn't optimal as there's a minor perf hit but it isn't noticeable overall.

To consider in future PRs:
- Add user configurable setting for max length?
- Handle case where we scroll to bottom but scrollbar is at the top. 
- Consider how intellisense will work on this. We may need to split into a window around the current code when sending to the kernel as it's quite likely that doing a 12K line intellisense request will be too big.
2019-02-09 13:44:53 -08:00
Kevin Cunnane
b964dd0895 Fix #3985 Hide cell toolbar for markdown cells (#3987)
* Fix #3985 Hide cell toolbar for markdown cells
* Note that I'm still hiding the overall toolbar section per UX feedback
* Also now hiding line numbers per UX feedback..
2019-02-08 16:38:28 -08:00
Raj
7dd32ed44b Notebook server shutdown error (#3976)
* fix #3959 - Notebook shutdown error

* Removing the unit test case to stopserver from clientSession
2019-02-08 13:51:00 -08:00
Chris LaFreniere
0b6aedfc93 Address notebook margin and border CSS issues (#3977) 2019-02-08 10:01:09 -10:00
Chris LaFreniere
b692088c94 Stop map column names for notebook grid, instead use field with unique values (#3975) 2019-02-08 09:59:36 -10:00
Karl Burtram
160ab8d0ae Bump html_query_plan to 2.6 (#3982) 2019-02-08 11:47:33 -08:00
Kevin Cunnane
a599cb436a Run upgrade on npm and yarn packages to update lodash to 4.1.7.11 (#3983)
- This is a recommended update, let me know if you have concerns
- Updated all samples and Azure Data Studio specific extensions with lodash dependency
2019-02-08 11:44:08 -08:00
Yurong He
294aa81298 Added serverVersion to contextProvider key, so Sql server preview das… (#3981)
* Added serverVersion to contextProvider key, so Sql server preview dashboard tab could be filter by it.

* User major version instead of serverVersion
2019-02-08 11:17:46 -08:00
Kevin Cunnane
ddc4b3dd6e Support execution count in run button and align correctly (#3979)
Fixes #3931 
- Align run button correctly so it's centered in new cell
- Refactor to support multi-state button.
  - Hidden state is set to show execution count
  - Stopped state shows run button
  - Running state shows stop button
  - Error state (will) show error button. This isn't fully handled right now
- Add execution count to model and to SqlKernel, verify serialization, loading, update matches other notebook viewers

**Notes on implementation**:
I think this is a decent solution for a) showing execution count as text, and b) perfectly centering the run button.
 
The below solution shows count correctly up to 999 runs (that’s clicking 999 times in a single session), the icon lines up juuust about right with [ ] but for other numbers it is pretty close but probably not exactly right. I wish I could solve this to work better but trying to change text float to center etc. really isn’t working.
 
**Screenshots**:
![image](https://user-images.githubusercontent.com/10819925/52466366-e8794200-2b36-11e9-9a50-86893e75d5af.png)

With running cell:
![image](https://user-images.githubusercontent.com/10819925/52466378-f333d700-2b36-11e9-9e6c-3cee098790fd.png)
2019-02-08 11:05:03 -08:00
Matt Irvine
4c5bf3ad2b Add insiders build links to readme (#3980) 2019-02-08 09:42:46 -08:00
Aditya Bist
88c33214c6 Dataexplorer viewlet (#3967)
* added initial data explorer viewlet

* added dataexplorer contribution point

* removed test view

* remove unused imports

* added flag and tests

* CR comments

* added icon for data explorer
2019-02-07 17:18:05 -08:00
kisantia
393be65aa6 Add Deploy Plan page to DacFx wizard (#3911)
* upgrade plan is piped through and returns the xml plan

* Added review deploy plan page

* checkbox validation now working and columns formatted

* formatting and cleaning up code

* refactored populateTable()

* addressing comments

* addressing comments

* updating tooltips

* add padding to table cells to align with headers

* fix problems when going back and forth between pages and changing config options

* bump sqltoolsservice version to 71

* fix localization
2019-02-07 16:39:22 -08:00
Chris LaFreniere
9ce9a1598f Improve notebook editor height calculations (#3966)
* Improve notebook editor height calculations

* PR comments, hook up to onDidChangeConfiguration
2019-02-07 14:09:09 -10:00
Yurong He
d9079fe18e Fixed #3888. Don't know why it works in previous extension not in mssql after ported. But look like needs utils.getErrorMessage to get msg. (#3969) 2019-02-07 11:47:53 -08:00
Yurong He
3cde070d3b Added submit spark job to data service context menu (#3968) 2019-02-07 11:46:59 -08:00
Karl Burtram
b2a5f65a77 Add query action bar spacing for XML button (#3923) 2019-02-07 11:33:23 -08:00
Kevin Cunnane
69dff5a2cb Fix #3937 Create new notebook (Mac) and receive TypeError (#3965)
- Handles empty file scenario, with fixes along the way for missing metadata (bonus win)
- In non-empty file still shows error and kernel stuck in loading state. #3964 opened to track this issue and fix later
2019-02-07 10:35:19 -08:00
Kevin Cunnane
40e0d5cfbf Fix toggle more actions staying visible, and clickable issues (#3949)
- Fixed so it's now invisible instead of empty when not selected.
 - This fixes clickability and issue where it stayed visible in 1 fix
- Also fixed cell output action which used active cell instead of context cell.
2019-02-07 09:35:58 -08:00
Raj
5a0100757f Attach To is set to 'Localhost' upon cancelling the connection dialog (#3941)
* #3924: Attach To sets 'Localhost' upon cancelling the connection dialog

* Indentation
2019-02-06 16:05:42 -08:00
Kevin Cunnane
f9fe88898d Fix #3928 'Clear output' in ... for markdown cells (#3935)
- Add filtering support for actions, and use for the Clear Output action
2019-02-06 15:49:20 -08:00
Anthony Dresser
a2d6955f79 check for undefined on query info (#3933) 2019-02-06 15:17:45 -08:00
Yurong He
8fa247145e As PM suggested, moved it to Data Services node. (#3930) 2019-02-06 14:22:37 -08:00
Yurong He
04bb65dcf7 Fixe Linux EMFILE: too many open file problem. (#3912)
* Fixe Linux EMFILE: too many open file problem.
Separated mssql from packageTask like azurecore.

* Make mssql depends on azurecore

* Minor fixes
2019-02-06 14:09:19 -08:00
Karl Burtram
e4884c7835 Bump SQL Tools Service to 1.5.0-alpha.70 2019-02-06 12:06:23 -08:00
Gene Lee
8b9ce3e8de Spark features with dashboard are enabled (#3883)
* Spark features are enabled

* Fixed as PR comments

* minor change

* PR comments fixed

* minor fix

* change constant name to avoid conflicts with sqlopsextension

* sqlContext to context

* Changed tab name to SQL Server Big Data Cluster

* Added isCluster to ContextProvider to control display big data cluster dashboard tab
Ported New/open Notebook code to mssql extension and enable them in dashboard

* Fixed tslint
2019-02-06 11:54:25 -08:00
kisantia
327a5f5fae Add tooltip for table column headers and align header and cell (#3909)
* Adding tooltip and lining up header and cell

* moving padding to separate css class
2019-02-06 11:46:24 -08:00
gbritton1
50b971477b Removed reference to object explorer (#3463)
Removed reference to object explorer since ADS does not have one
2019-02-06 10:43:46 -08:00
Anthony Dresser
07c7eea2df reverse data array on repopulation (#3907) 2019-02-06 10:41:55 -08:00
Raj
42135d3e53 #3897: Unified connection integration - sql connection improvements (#3910)
* #3897: Unified connection integration - sql connection improvements

* variable name change

* Misc changes

* Misc change
2019-02-06 10:33:21 -08:00
Kevin Cunnane
d74e5e6457 Fix regression where border line between editor and output was lost (#3915) 2019-02-05 21:21:59 -08:00
Kevin Cunnane
a2c7377134 Improve notebook colors and UX (#3914)
This was reviewed / worked on with Smitha and will be signed off on by PM via mail.
1 thing left (make run button look better when not selected) will be one in separate review.

Changes
- Add top/bottom padding to editor so it's not cramped
- Added an (on by default) setting `notebook.overrideEditorTheming`. This controls whether new colors etc. are used for notebook editors or if users should see vanilla UI like in standard editor. Settings under this flag are:
  - When unselected, editor has same color as toolbar. On selection it goes back to regular editor view so colors work "right"
  - In standard light/dark themes we now use a filled in background color instead of border box.
2019-02-05 17:51:42 -08:00
Raj
0e54393d5a Unified connection in notebooks (#3898)
* yarn files

* #3897: Integrate unified connection with notebooks

* ConnectionProfile serialization in unified connection

* #3898 Handle connection validation from extension

* Removing unused namespaces

* Remove constant

* Show a detailed error message on changing context

* Indentation
2019-02-05 11:54:29 -08:00
Yurong He
8cf8cefc92 Removed dup OE contribution. The conflict wasn't detected during checkin. (#3906) 2019-02-05 11:36:33 -08:00
Kevin Cunnane
098c40e9ac Use document-style for Notebooks (#3902)
* Added hover support, adding box shadow and light outline on hovering and the "more actions" button showing on hover
* Added box shadow for dark themes (hooray!)
* Remove border from everything but the code cell unless a cell is selected or hovered over. This ensures this looks like a document
* Fix high contrast theming issues.
2019-02-05 11:28:07 -08:00
Yurong He
80c1c4c6c8 Mssql extension exposes OE getNode API for Sql-2019vNext extension (#3901)
* Mssql extension exposes OE getNode API for Sql-2019Vnext extension

* Resolved PR comments
2019-02-04 19:55:32 -08:00
Yurong He
ef8afab7e8 Added error node to OE tree (#3889)
* Add error node to OE tree

* Add globalerror_red.svg for error node.

* Fixed wrong import resolved automatically

* Resolve PR comments
2019-02-04 19:18:58 -08:00
Yurong He
84e0e08aec Ported Analyze notebook code from SqlOpsStudio and make it work. (#3899)
* Ported Analyze notebook code from SqlOpsStudio and make it work.
if config.notebook.sqlKernelEnabled is true, use SQL provider;
Use Jupyter provider if Python is install, otherwise use buildIn Kernel.

* Analyze in Notebook Kernel can only be Python or "No Kernel". So remove Sql Kernel.
2019-02-04 15:41:01 -08:00
Kevin Cunnane
2fce771214 Run and Add Cell keybinding support (#3896)
- As part of this, fixed bug in the insertCell API where it didn't add to the end / failed if no cells existed
2019-02-04 14:02:15 -08:00
Yurong He
15929e8cf2 Add new notebook to OE server context menu (#3892) 2019-02-04 11:25:33 -08:00
Kevin Cunnane
f1c8ec141a Make run cell button float so it's always visible (#3895)
- Make the toolbar sticky and remove overflow:hidden which blocked this working.
2019-02-04 09:32:38 -08:00
kisantia
a62393e0ed Add width and css options for TableColumn (#3893) 2019-02-02 19:27:35 -08:00
Yurong He
a6defd9b62 Fixed build issue: ERROR: D:/a/1/s/src/sql/workbench/services/notebook/common/sqlSessionManager.ts[21, 1]: Duplicate imports for 'sqlops'. (#3894) 2019-02-01 14:39:09 -08:00
Kevin Cunnane
374212beaa Fix bug where results were added to all cells, and support multiple resultsets (#3890)
- SQLKernel is the only place to listen for batch and query complete messages now
- It routes to the 1 and only future (since can only have 1 at a time
- It handles query cancelation and not-connected issues correctly
2019-02-01 13:53:10 -08:00
Kevin Cunnane
5132e62045 Fix #3734 Notebook cells are shown empty some times even when there is content (#3878)
- Editor layout gets called sometimes when other events happen (and Notebook isn't visible)
- Add in a layout call on re-setting input so the cell is updated. This fixes the problem by laying out once the UI is visible again.

Note: long term, should really be destroying the UI (while preserving the model), then restoring it including scroll selection etc. and hooking back up to the model. That is... much more work, but something we'll need long term to avoid issues where we have many Notebooks open at once. Not in scope for this PR
2019-02-01 10:11:45 -08:00
Kevin Cunnane
9504ede1f3 Fix #3875 Notebook stuck Loading Kernels if SQL flag disabled and Jupyter not installed (#3876) 2019-02-01 10:10:21 -08:00
Kevin Cunnane
afb6e6b5ba Fix some cell UI issues (toolbar background color, unselected cells) (#3881)
- Toolbar background is now differentiated from the editor
- For unselected cells there's no longer a line selection in the cell. This makes it clearer what the active cell is (and cleans the UI up)
2019-02-01 08:03:23 -08:00
Yurong He
60b2b92803 Fixed #3873 with update the version of vscode-nls (#3879)
Fixed #3873 with update the version of vscode-nls (#3879)
Added dependencies needed for prompts.
2019-01-31 17:57:04 -08:00
Aditya Bist
6113311fda preserve whitespace in messages (#3821) 2019-01-31 15:23:10 -08:00
Yurong He
ecac6201d0 Rename nodeType name in order to have file context menu in both mssql and SqlOpsStudio (#3862)
* Added data service context menu: file related operations. All new files are ported from SqlOpsStudio. Will remove these functionality from SqlOpsStudio.

* Used the existing constant hadoopKnoxEndpointName

* Rename nodeType name from hdfs to bdc. So we can have file context menu in both mssql and SqlOpsStudio. Need to add "Create External Table from CSV" support for bdc nodeType

* Rename bdc to mssqlcluster
2019-01-31 13:34:59 -08:00
Chris LaFreniere
90d8c37f91 Fix a not implemented issue when we were not sanitizing kernel display name (#3869)
Fixing an issue where we got a 501 Not Implemented because kernel display name sanitization was not occurring with the _defaultKernel case.

In addition, changed a method name to make it more clear, and removed an erroneous error that would occur every time you opened a notebook without any existing connections. I'm just removing this, as it adds no value.
2019-01-31 09:50:27 -08:00
Chris LaFreniere
c43085beab Fix weird exception when no connection is present for SQL kernel, Limit Max Rows to 2000 (#3870)
Fixes #3856. Matches the Jupyter behavior that we have, where we don't show any message when a connection is required. We no longer will throw a bizarre exception about getOptionsKey being undefined.

Also sets max rows returned to 2000.
2019-01-31 09:38:59 -08:00
Kevin Cunnane
d9c383b2ef Remove notebook.enabled feature flag (#3866)
* Remove notebook.enabled feature flag

* Fix build error with package.json typos
2019-01-31 09:34:50 -08:00
Matt Irvine
100938b0e5 Add bytes dependency to mssql (#3867) 2019-01-30 17:29:41 -08:00
Chris LaFreniere
83a6ee0a22 Change feature flag for SQL kernel to be user preference (#3838)
* Change feature flag for SQL kernel to be user preference

* fix test that was broken

* Tweak package.nls.json to show "(Preview)"
2019-01-30 17:29:08 -08:00
Chris LaFreniere
0dab7f02ed Notebooks: Grid Support (#3832)
* First grid support in notebooks

* still trying to get nteract ipynb to display grid correctly

* works opening with existing 'application/vnd.dataresource+json' table

* fixing merge issue due to core folder structure changing a bit

* PR feedback, fix for XSS
2019-01-30 16:56:14 -08:00
Chris LaFreniere
0e6f2eb1cd Only show placeholder when notebook isn't loading (#3863) 2019-01-30 16:22:24 -08:00
Chris LaFreniere
9a371f8998 Fix for Select Connection not showing up in Attach To (#3860) 2019-01-30 16:22:01 -08:00
David Shiflet
8a7bbd1795 Pass connectionid to registered commands from command line (#3861)
* pass connectionid to registered commands from commandline

* remove blank lines

* fix commandline unit test
2019-01-30 18:18:25 -05:00
Kevin Cunnane
d1fef24723 Support Notebook integration testing by adding APIs & fixing others (#3848)
- Added `runCell` API. Updated runCell button to listen to events on the model so it'll reflect run cell when called from other sources
- Plumbed through kernelspec info to the extension side so when changed, it's updated
- Fixed bug in ConnectionProfile where it didn't copy from options but instead overrode with empty wrapper functions

Here's the rough test code (it's in the sql-vnext extension and will be out in a separate PR)
```ts

    it('Should connect to local notebook server with result 2', async function() {
        this.timeout(60000);
        let pythonNotebook = Object.assign({}, expectedNotebookContent, { metadata: { kernelspec: { name: "python3", display_name: "Python 3" }}});
        let uri = writeNotebookToFile(pythonNotebook);
        await ensureJupyterInstalled();

        let notebook = await sqlops.nb.showNotebookDocument(uri);
        should(notebook.document.cells).have.length(1);
        let ran = await notebook.runCell(notebook.document.cells[0]);
        should(ran).be.true('Notebook runCell failed');
        let cellOutputs = notebook.document.cells[0].contents.outputs;
        should(cellOutputs).have.length(1);
        let result = (<sqlops.nb.IExecuteResult>cellOutputs[0]).data['text/plain'];
        should(result).equal('2');

        try {
            // TODO support closing the editor. Right now this prompts and there's no override for this. Need to fix in core
            // Close the editor using the recommended vscode API
            //await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
        }
        catch (e) {}
    });

    it('Should connect to remote spark server with result 2', async function() {
        this.timeout(240000);
        let uri = writeNotebookToFile(expectedNotebookContent);
        await ensureJupyterInstalled();

        // Given a connection to a server exists
        let connectionId = await connectToSparkIntegrationServer();

        // When I open a Spark notebook and run the cell
        let notebook = await sqlops.nb.showNotebookDocument(uri, {
            connectionId: connectionId
        });
        should(notebook.document.cells).have.length(1);
        let ran = await notebook.runCell(notebook.document.cells[0]);
        should(ran).be.true('Notebook runCell failed');

        // Then I expect to get the output result of 1+1, executed remotely against the Spark endpoint
        let cellOutputs = notebook.document.cells[0].contents.outputs;
        should(cellOutputs).have.length(4);
        let sparkResult = (<sqlops.nb.IStreamResult>cellOutputs[3]).text;
        should(sparkResult).equal('2');

        try {
            // TODO support closing the editor. Right now this prompts and there's no override for this. Need to fix in core
            // Close the editor using the recommended vscode API
            //await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
        }
        catch (e) {}
    });
});
```
2019-01-30 14:24:14 -08:00
Yurong He
3ddc5e7846 Added Unified connection support (#3785)
* Added Unified connection support

* Use generic way to do expandNode.
Cleanup the ported code and removed unreference code. Added as needed later.
Resolved PR comments.

* Minor fixes and removed timer for all expanders for now. If any providers can't response, the tree node will spin and wait. We may improve later.

* Change handSessionClose to not thenable.
Added a node to OE to show error message instead of reject. So we could show partial expanded result if get any.
Resolve PR comments

* Minor fixes of PR comments
2019-01-29 14:37:14 -08:00
Yurong He
b439ea45ec Bump to 69 to fix #3839 doesn't have model.sys.assemblies (#3842) 2019-01-29 10:09:45 -08:00
Karl Burtram
5680785f86 Bump Azure Data Studio to 1.4.4 2019-01-28 15:58:14 -08:00
Chris LaFreniere
e8eb7bec1b Fix notebook selection issues including from placeholder (#3836) 2019-01-28 14:02:23 -08:00
kisantia
565b7404f9 Add generate script option to DacFx wizard (#3789)
* Add generate script option to deploy scenario

* add action to summary page and fixed page adding/removing so that summary page will have the correct step number

* updating contract based on change in sqltoolsservice

* added enums to make index checks more clear

* cleaned up onPageChanged()

* bump sqltoolsservice version to 68
2019-01-28 10:48:36 -08:00
Chris LaFreniere
9cffe4d476 Allow for "when" clause filtering for Notebook Toolbar Given ProviderId Changes (#3712)
* Integrate first SQL Notebooks Bits into Master (#3679)

* First crack tsql notebook (no output rendered yet)

* getting messages back

* intellisense working first cell, no connection errors

* sql notebook cell output functioning

* Latest SQL noteobook changes

* Undo change to launch.json

* Plumbing providers through

* Kernels shown from multiple providers, can switch between them. No mementos yet

* Ensure we have a feature flag for SQL notebooks, ensure existing functionality still works

* Fix tslint duplicate imports issue

* Addressing PR comments

* second round of PR feedback to cleanup notebook service manager code

* merge latest from master

* Enable notebook toolbar actions to disable themselves on provider change

* Undo changes to taskbar/actionbar

* very minor change due to latest merge
2019-01-26 11:01:40 -08:00
Chris LaFreniere
43be88a37c SQL Kernel Improvements/Removing Spark Code from Core/Attach to Changes (#3790)
* Scenarios work besides loading saved kernel

* Fix compilation issue

* Save and load functional

* Fix loading kernesl issue when sql kernel is not enabled

* Fix language mapping to not be hardcoded any longer

* Remove unnecessary comment

* PR Comments vol. 1

* Code cleanup, use ConnectionProfile instead of IConnectionProfile when accessing serverName

* PR changes vol. 2

* One final comment for PR

* Fix linting issue
2019-01-25 18:54:04 -08:00
Anthony Dresser
ea67859de7 Initial Code Layering (#3788)
* working on formatting

* fixed basic lint errors; starting moving things to their appropriate location

* formatting

* update tslint to match the version of vscode we have

* remove unused code

* work in progress fixing layering

* formatting

* moved connection management service to platform

* formatting

* add missing file

* moving more servies

* formatting

* moving more services

* formatting

* wip

* moving more services

* formatting

* revert back tslint rules

* move css file

* add missing svgs
2019-01-25 14:52:35 -08:00
Aditya Bist
c8986464ec fixed arrows disappearing after tab change (#3829) 2019-01-25 13:29:39 -08:00
Aditya Bist
7804f94d8b Copy all messages when selecting all (#3818)
* copy all messages when selecting all

* added functionality for keyboard shortcuts

* fixed bug when select all then selection made

* made output similar to debug console
2019-01-25 12:10:00 -08:00
Alan Ren
bfa77aebfc add clear filter icon and update filter icon from Smitha (#3828) 2019-01-25 11:34:58 -08:00
Yurong He
487fb02313 Bump sqltoolservice version to 67 for unified connection support (#3827) 2019-01-25 11:24:26 -08:00
Aditya Bist
ef64038107 Added horizontal scrolling for explorer (#3819)
* added horizontal scrolling for explorer

* made horizontal scrolling auto
2019-01-24 13:31:19 -08:00
udeeshagautam
5d336accbc adding hover text for dashboard serach grid items (#3816)
Fix for issue : Search widget in Manage dashboard truncates long names with no hovertext to show full name (Ref issue: #3075)
2019-01-24 13:17:37 -08:00
Karl Burtram
99047b2866 Remove Ctrl-Alt keyboard shortcuts (#3810) 2019-01-23 17:23:59 -08:00
Aditya Bist
f611cf3b5a Improve Agent performance (#3804)
* pause and resume job history retrieval when opening dialogs

* review comments

* removed boolean for tab change
2019-01-23 14:25:54 -08:00
Karl Burtram
4ad059605c Update Azure account picker styles based on splitview change (#3791) 2019-01-23 10:50:41 -08:00
Karl Burtram
dc2ff97dd8 Bump Azure Data Studio to 1.4.3 2019-01-22 16:54:51 -08:00
Karl Burtram
2b5265c103 Fix infinite callbacks in Azure Resource Explorer (#3780) 2019-01-22 15:22:45 -08:00
Aditya Bist
2e98fde053 fixed resizing in agent because of slickgrid change (#3786) 2019-01-22 14:38:20 -08:00
Anthony Dresser
d5176e0eb7 remove updating row number column size (#3756) 2019-01-22 14:37:59 -08:00
Anthony Dresser
eb0b2a847b change stating to handle magnify state (#3746)
* change stating to handle magnify state

* fix magnify during state setup
2019-01-22 14:37:33 -08:00
Aditya Bist
cff5482f69 Show Azure Data Studio instead of azuredatastudio when updating (#3787)
* show Azure Data Studio instead of azuredatastudio when updating

* added sql carbon tag
2019-01-22 10:58:40 -08:00
Alan Ren
afc37973d0 Update readme.md 2019-01-22 10:53:26 -08:00
Alan Ren
3eada6c6ab Create readme.md 2019-01-22 10:21:18 -08:00
Aditya Bist
7c39268fe5 Agent - bug fixes and mini features (#3637)
* fixed scrollbar in jobs

* show steps tree when job history is opened

* cleaned and added edit job to job history

* scrollbars on step details

* steps scrolling done

* fixed styling

* fixed keyboard selection, navigation and UI

* fixed tabbing accessibility

* added refresh action to job history

* fixed focus on move step

* added remove schedule button

* fixed various bugs

* added errors for all actions

* review comments
2019-01-22 10:01:13 -08:00
Alan Ren
eb67b299de Alanren/integration test (#3657)
* add an extension for integration tests

* setup ads before running test

* test setup

* test cases

* bash script

* shorter temp folder name

* code cleanup

* add commented out original code

* fix test error

* test result path

* rename results file

* change file path

* report smoke test results

* test stablize

* test stablization and configurable test servers

* fix smoke test error

* connection provider

* simplify the integration test script

* add comment

* fix tslint error

* address PR comments

* add temp log to check whether the environment variable is already set

* remove temp log

* move api definition to testapi typing file

* exclude integration tests extension

* address comments
2019-01-18 17:00:30 -08:00
Alan Ren
3e7a09c1e3 Alanren/profiler filter (#3760)
* profiler filter

* add test cases

* perf improvement with bulk insert

* update dependency version and address comments
2019-01-18 16:25:18 -08:00
Karl Burtram
637dc9b9b2 Bump Azure Data Studio to 1.4.2 2019-01-18 09:48:44 -08:00
Karl Burtram
1de16d4715 Reset query messages for each execution (#3772) 2019-01-17 17:53:05 -08:00
Kevin Cunnane
49090d774d Null ref occurred when doing some UI interactions before the notebook model was set (#3769) 2019-01-17 14:41:56 -08:00
Karl Burtram
9a695b5cdd Reenable results stream by default (#3752) 2019-01-17 10:28:48 -08:00
Raj
e0339b50c0 #3753: User settings configuration - python installation path (#3754)
* #3753: User settings configuration - python installation path

* Text change

* #3753: Text change

* Message change
2019-01-16 16:29:06 -08:00
Karl Burtram
d0c584672f Fix Top Operations tab title (#3751) 2019-01-15 16:06:51 -08:00
Anthony Dresser
27816acaeb Remove custom splitview (#3467)
* working on options dialog

* working through options dialog

* trying to work through modifying options dialog

* working on converting scrollablesplitview

* fixed options working through profiler

* fix profiler

* fix account dialog

* trying to fix problems with splitpanel

* fix insights dialog

* moving through

* fix last list, need to verify looks and functionality

* fix look of account dialog

* formatting

* formatting

* working through scrollable bugs

* working on problem with view size

* fix margin issues

* fix styler for dialogs

* add panel styles to insights

* create instantiation issues

* fix test

* fix test

* remove unused code

* formatting

* working through insight dialog issues

* fix table updating

* remove console logs
2019-01-15 15:00:34 -08:00
Mustafa Sadedil
4de3cc8a09 Completed: Missing feature request: Save as XML (#3729)
* Save as XML feature added to grid

* Unrelated code removed
2019-01-15 14:36:42 -08:00
Karl Burtram
5c16ceb2fa Bump SQL Tools Service to pick up https://github.com/Microsoft/sqltoolsservice/pull/763 (#3748) 2019-01-15 14:12:20 -08:00
Raj
9db3f73413 Notebook Doesn't Prompt for Save even when isDirty #3568 (#3656)
This is temp fix until native save is implemented.
2019-01-15 11:41:05 -08:00
Chris LaFreniere
e0ceddce09 Notebooks: Add Placeholder Cell, Fix Link Styling (#3728)
* Placeholder cell to add new real cells

* Fix links in notebooks to show correct color, rely on angular ngif for placeholder

* Fix failing test where one cell was expected by default

* Remove unnecessary TODO
2019-01-14 17:29:06 -08:00
Chris LaFreniere
6dc4096299 Editor focus based on activeCell, create text in edit, scroll to active (#3725) 2019-01-14 16:39:36 -08:00
Chris LaFreniere
1fa03b5c74 Ensure we always get all providers (#3724) 2019-01-14 16:38:57 -08:00
Kevin Cunnane
f8f57a93c3 Fix #3736 Notebook: cannot connect to SQL big data cluster due to empty config.json file (#3738)
- Writing the config file in the core for now, will look to move to the extension in Feb release
2019-01-14 14:14:32 -08:00
Karl Burtram
960fe63312 Bump Data Protocol client to 0.2.11 (#3739) 2019-01-14 14:04:35 -08:00
Karl Burtram
7545b94128 Turn off "something went wrong" message (#3606) 2019-01-11 17:39:13 -08:00
12266 changed files with 179345 additions and 285633 deletions

View File

@@ -1,19 +0,0 @@
{
"env": {
"node": true,
"es6": true
},
"rules": {
"no-console": 0,
"no-cond-assign": 0,
"no-unused-vars": 1,
"no-extra-semi": "warn",
"semi": "warn"
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
}

20
.eslintrc.json Normal file
View File

@@ -0,0 +1,20 @@
{
"root": true,
"env": {
"node": true,
"es6": true
},
"rules": {
"no-console": 0,
"no-cond-assign": 0,
"no-unused-vars": 1,
"no-extra-semi": "warn",
"semi": "warn"
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
}

49
.github/classifier.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
{
perform: true,
alwaysRequireAssignee: false,
labelsRequiringAssignee: [],
autoAssignees: {
accessibility: [],
acquisition: [],
agent: [],
azure: [],
backup: [],
bcdr: [],
'chart viewer': [],
connection: [],
dacfx: [],
dashboard: [],
'data explorer': [],
documentation: [],
'edit data': [],
export: [],
extensibility: [],
extensionManager: [],
globalization: [],
grid: [],
import: [],
insights: [],
intellisense: [],
localization: [],
'managed instance': [],
notebooks: [],
'object explorer': [],
performance: [],
profiler: [],
'query editor': [],
'query execution': [],
reliability: [],
restore: [],
scripting: [],
'server group': [],
settings: [],
setup: [],
shell: [],
showplan: [],
snippet: [],
sql2019Preview: [],
sqldw: [],
supportability: [],
ux: []
}
}

12
.github/commands.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
{
perform: false,
commands: [
{
type: 'label',
name: 'duplicate',
allowTriggerByBot: true,
action: 'close',
comment: "Thanks for creating this issue! We figured it's covering the same as another one we already have. Thus, we closed this one as a duplicate. You can search for existing issues [here](https://aka.ms/vscodeissuesearch). See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
}
]
}

5
.github/copycat.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
{
perform: true,
target_owner: 'anthonydresser',
target_repo: 'testissues'
}

6
.github/locker.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
{
daysAfterClose: 45,
daysSinceLastUpdate: 3,
ignoredLabels: [],
perform: true
}

6
.github/needs_more_info.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
{
daysUntilClose: 7,
needsMoreInfoLabel: 'more info',
perform: false,
closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
}

6
.github/new_release.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
{
newReleaseLabel: 'new-release',
newReleaseColor: '006b75',
daysAfterRelease: 5,
perform: true
}

5
.github/similarity.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
{
perform: true,
whenCreatedByTeam: true,
comment: "Thanks for submitting this issue. Please also check if it is already covered by an existing one, like:\n${potentialDuplicates}"
}

3
.gitignore vendored
View File

@@ -3,6 +3,7 @@ npm-debug.log
Thumbs.db Thumbs.db
node_modules/ node_modules/
.build/ .build/
extensions/**/dist/
out/ out/
out-build/ out-build/
out-editor/ out-editor/
@@ -17,4 +18,4 @@ build/node_modules
coverage/ coverage/
test_data/ test_data/
test-results/ test-results/
yarn-error.log yarn-error.log

23
.vscode/cglicenses.schema.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"licenseDetail"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the dependency"
},
"licenseDetail": {
"type": "array",
"description": "The complete license text of the dependency",
"items": {
"type": "string"
}
}
}
}
}

142
.vscode/cgmanifest.schema.json vendored Normal file
View File

@@ -0,0 +1,142 @@
{
"type": "object",
"properties": {
"registrations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"component": {
"oneOf": [
{
"type": "object",
"required": [
"type",
"git"
],
"properties": {
"type": {
"type": "string",
"enum": [
"git"
]
},
"git": {
"type": "object",
"required": [
"name",
"repositoryUrl",
"commitHash"
],
"properties": {
"name": {
"type": "string"
},
"repositoryUrl": {
"type": "string"
},
"commitHash": {
"type": "string"
}
}
}
}
},
{
"type": "object",
"required": [
"type",
"npm"
],
"properties": {
"type": {
"type": "string",
"enum": [
"npm"
]
},
"npm": {
"type": "object",
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
}
}
}
}
},
{
"type": "object",
"required": [
"type",
"other"
],
"properties": {
"type": {
"type": "string",
"enum": [
"other"
]
},
"other": {
"type": "object",
"required": [
"name",
"downloadUrl",
"version"
],
"properties": {
"name": {
"type": "string"
},
"downloadUrl": {
"type": "string"
},
"version": {
"type": "string"
}
}
}
}
}
]
},
"repositoryUrl": {
"type": "string",
"description": "The git url of the component"
},
"version": {
"type": "string",
"description": "The version of the component"
},
"license": {
"type": "string",
"description": "The name of the license"
},
"developmentDependency": {
"type": "boolean",
"description": "This component is inlined in the vscode repo and **is not shipped**."
},
"isOnlyProductionDependency": {
"type": "boolean",
"description": "This component is shipped and **is not inlined in the vscode repo**."
},
"licenseDetail": {
"type": "array",
"items": {
"type": "string"
},
"description": "The license text"
}
}
}
}
}
}

View File

@@ -2,7 +2,7 @@
// See https://go.microsoft.com/fwlink/?LinkId=827846 // See https://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format // for the documentation about the extensions.json format
"recommendations": [ "recommendations": [
"eg2.tslint", "ms-vscode.vscode-typescript-tslint-plugin",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"msjsdiag.debugger-for-chrome" "msjsdiag.debugger-for-chrome"
] ]

86
.vscode/launch.json vendored
View File

@@ -9,14 +9,12 @@
"stopOnEntry": true, "stopOnEntry": true,
"args": [ "args": [
"hygiene" "hygiene"
], ]
"cwd": "${workspaceFolder}"
}, },
{ {
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"name": "Attach to Extension Host", "name": "Attach to Extension Host",
"protocol": "inspector",
"port": 5870, "port": 5870,
"restart": true, "restart": true,
"outFiles": [ "outFiles": [
@@ -24,19 +22,15 @@
] ]
}, },
{ {
"type": "node", "type": "chrome",
"request": "attach", "request": "attach",
"name": "Attach to Shared Process", "name": "Attach to Shared Process",
"protocol": "inspector", "port": 9222,
"port": 5871, "urlFilter": "*"
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
}, },
{ {
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"protocol": "inspector",
"name": "Attach to Search Process", "name": "Attach to Search Process",
"port": 5876, "port": 5876,
"outFiles": [ "outFiles": [
@@ -47,7 +41,6 @@
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"name": "Attach to CLI Process", "name": "Attach to CLI Process",
"protocol": "inspector",
"port": 5874, "port": 5874,
"outFiles": [ "outFiles": [
"${workspaceFolder}/out/**/*.js" "${workspaceFolder}/out/**/*.js"
@@ -57,7 +50,6 @@
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"name": "Attach to Main Process", "name": "Attach to Main Process",
"protocol": "inspector",
"port": 5875, "port": 5875,
"outFiles": [ "outFiles": [
"${workspaceFolder}/out/**/*.js" "${workspaceFolder}/out/**/*.js"
@@ -82,9 +74,9 @@
"linux": { "linux": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh" "runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
}, },
"urlFilter": "*index.html*", "urlFilter": "*workbench.html*",
"runtimeArgs": [ "runtimeArgs": [
"--inspect=5875" "--inspect=5875", "--no-cached-data"
], ],
"skipFiles": [ "skipFiles": [
"**/winjs*.js" "**/winjs*.js"
@@ -116,34 +108,6 @@
"webRoot": "${workspaceFolder}", "webRoot": "${workspaceFolder}",
"timeout": 45000 "timeout": 45000
}, },
{
"type": "node",
"request": "launch",
"name": "Unit Tests",
"protocol": "inspector",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceFolder}/.build/electron/Azure Data Studio.app/Contents/MacOS/Electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/azuredatastudio.exe"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/azuredatastudio"
},
"stopOnEntry": false,
"outputCapture": "std",
"args": [
"--delay",
"--timeout",
"2000"
],
"cwd": "${workspaceFolder}",
"env": {
"ELECTRON_RUN_AS_NODE": "true"
},
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
},
{ {
"name": "Launch Built-in Extension", "name": "Launch Built-in Extension",
"type": "extensionHost", "type": "extensionHost",
@@ -152,9 +116,47 @@
"args": [ "args": [
"--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch" "--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch"
] ]
},
{
"type": "node",
"request": "launch",
"name": "Launch Smoke Test",
"program": "${workspaceFolder}/test/smoke/test/index.js",
"cwd": "${workspaceFolder}/test/smoke",
"env": {
"BUILD_ARTIFACTSTAGINGDIRECTORY": "${workspaceFolder}"
}
},
{
"type": "node",
"request": "launch",
"name": "Run Unit Tests",
"program": "${workspaceFolder}/test/electron/index.js",
"runtimeExecutable": "${workspaceFolder}/.build/electron/Azure Data Studio.app/Contents/MacOS/Electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/azuredatastudio.exe"
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/azuredatastudio"
},
"outputCapture": "std",
"args": [
"--remote-debugging-port=9222"
],
"cwd": "${workspaceFolder}",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
} }
], ],
"compounds": [ "compounds": [
{
"name": "Debug Unit Tests",
"configurations": [
"Attach to azuredatastudio",
"Run Unit Tests"
]
},
{ {
"name": "Debug azuredatastudio Main and Renderer", "name": "Debug azuredatastudio Main and Renderer",
"configurations": [ "configurations": [

16
.vscode/settings.json vendored
View File

@@ -11,7 +11,7 @@
} }
}, },
"files.associations": { "files.associations": {
"OSSREADME.json": "jsonc" "cglicenses.json": "jsonc"
}, },
"search.exclude": { "search.exclude": {
"**/node_modules": true, "**/node_modules": true,
@@ -22,9 +22,9 @@
"out-vscode/**": true, "out-vscode/**": true,
"i18n/**": true, "i18n/**": true,
"extensions/**/out/**": true, "extensions/**/out/**": true,
"test/smoke/out/**": true "test/smoke/out/**": true,
"src/vs/base/test/node/uri.test.data.txt": true
}, },
"tslint.enable": true,
"lcov.path": [ "lcov.path": [
"./.build/coverage/lcov.info", "./.build/coverage/lcov.info",
"./.build/coverage-single/lcov.info" "./.build/coverage-single/lcov.info"
@@ -43,6 +43,12 @@
"git.ignoreLimitWarning": true, "git.ignoreLimitWarning": true,
"emmet.excludeLanguages": [], "emmet.excludeLanguages": [],
"typescript.preferences.importModuleSpecifier": "non-relative", "typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.quoteStyle": "single" "typescript.preferences.quoteStyle": "single",
"json.schemas": [{
"fileMatch": [ "cgmanifest.json" ],
"url": "./.vscode/cgmanifest.schema.json"
}, {
"fileMatch": [ "cglicenses.json" ],
"url": "./.vscode/cglicenses.schema.json"
}]
} }

38
.vscode/shared.code-snippets vendored Normal file
View File

@@ -0,0 +1,38 @@
{
// Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. The scope defines in watch languages the snippet is applicable. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted.Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
"MSFT Copyright Header": {
"scope": "javascript,typescript,css",
"prefix": [
"header",
"stub",
"copyright"
],
"body": [
"/*---------------------------------------------------------------------------------------------",
" * Copyright (c) Microsoft Corporation. All rights reserved.",
" * Licensed under the Source EULA. See License.txt in the project root for license information.",
" *--------------------------------------------------------------------------------------------*/",
"",
"$0"
],
"description": "Insert Copyright Statement"
},
"TS -> Inject Service": {
"description": "Constructor Injection Pattern",
"prefix": "@inject",
"body": "@$1 private readonly _$2: ${1},$0"
},
"TS -> Event & Emitter": {
"prefix": "emitter",
"description": "Add emitter and event properties",
"body": [
"private readonly _onDid$1 = new Emitter<$2>();",
"readonly onDid$1: Event<$2> = this._onDid$1.event;"
],
}
}

17
.vscode/tasks.json vendored
View File

@@ -28,6 +28,23 @@
} }
} }
}, },
{
"type": "npm",
"script": "strict-null-check-watch",
"label": "TS - Strict Null Checks",
"isBackground": true,
"presentation": {
"reveal": "never"
},
"problemMatcher": {
"base": "$tsc-watch",
"owner": "typescript-strict-null",
"applyTo": "allDocuments"
},
"runOptions": {
"runOn": "folderOpen"
}
},
{ {
"type": "gulp", "type": "gulp",
"task": "tslint", "task": "tslint",

View File

@@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron" disturl "https://atom.io/download/electron"
target "2.0.9" target "2.0.12"
runtime "electron" runtime "electron"

View File

@@ -1,5 +1,30 @@
# Change Log # Change Log
## Version 1.4.5
* Release date: February 13, 2019
* Release status: General Availability
## What's new in this version
* Added **Admin pack for SQL Server** extension pack to make it easier to install SQL Server admin-related extensions. This includes:
* [SQL Server Agent](https://docs.microsoft.com/en-us/sql/azure-data-studio/sql-server-agent-extension?view=sql-server-2017)
* [SQL Server Profiler](https://docs.microsoft.com/en-us/sql/azure-data-studio/sql-server-profiler-extension?view=sql-server-2017)
* [SQL Server Import](https://docs.microsoft.com/en-us/sql/azure-data-studio/sql-server-import-extension?view=sql-server-2017)
* Added filtering extended event support in Profiler extension
* Added Save as XML feature that can save T-SQL results as XML
* Added Data-Tier Application Wizard improvements
* Added Generate script button
* Added view to give warnings of possible data loss during deployment
* Updates to the [SQL Server 2019 Preview extension](https://docs.microsoft.com/sql/azure-data-studio/sql-server-2019-extension?view=sql-server-ver15)
* Results streaming enabled by default for long running queries
* Resolved [bugs and issues](https://github.com/Microsoft/azuredatastudio/milestone/23?closed=1).
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277`
* sadedil for `Missing feature request: Save as XML #3729`
* gbritton1 for `Removed reference to object explorer #3463`
## Version 1.3.8 ## Version 1.3.8
* Release date: January 9, 2019 * Release date: January 9, 2019
* Release status: General Availability * Release status: General Availability

View File

@@ -18,7 +18,9 @@ File a single issue per problem and feature request.
* Do not enumerate multiple bugs or feature requests in the same issue. * Do not enumerate multiple bugs or feature requests in the same issue.
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes. * Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix. The more information you can provide, the more likely someone will be successful at reproducing the issue and finding a fix.
The built-in tool for reporting an issue, which you can access by using `Report Issue` in Azure Data Studio's Help menu, can help streamline this process by automatically providing the version of Azure Data Studio, all your installed extensions, and your system info.
Please include the following with each issue. Please include the following with each issue.

File diff suppressed because it is too large Load Diff

View File

@@ -9,17 +9,22 @@ Azure Data Studio is a data management tool that enables you to work with SQL Se
Platform | Link Platform | Link
-- | -- -- | --
Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2049972 Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2072725
Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2049975 Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2072728
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2050146 Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2072354
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2049981 macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2072737
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2049986 Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2072360
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2049989 Linux RPM | https://go.microsoft.com/fwlink/?linkid=2072741
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2050157 Linux DEB | https://go.microsoft.com/fwlink/?linkid=2072744
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions. Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
Try out the latest insiders build from `master` at https://github.com/Microsoft/azuredatastudio/releases. Try out the latest insiders build from `master`:
- [Windows User Installer - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64-user/insider)
- [Windows System Installer - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64/insider)
- [Windows ZIP - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64-archive/insider)
- [macOS ZIP - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/darwin/insider)
- [Linux TAR.GZ - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/linux-x64/insider)
See the [change log](https://github.com/Microsoft/azuredatastudio/blob/master/CHANGELOG.md) for additional details of what's in this release. See the [change log](https://github.com/Microsoft/azuredatastudio/blob/master/CHANGELOG.md) for additional details of what's in this release.
@@ -63,6 +68,9 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
## Contributions and "Thank You" ## Contributions and "Thank You"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes: We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277`
* sadedil for `Missing feature request: Save as XML #3729`
* gbritton1 for `Removed reference to object explorer #3463`
* Tarig0 for `Add Routine_Type to CreateStoredProc fixes #3257 (#3286)` * Tarig0 for `Add Routine_Type to CreateStoredProc fixes #3257 (#3286)`
* oltruong for `typo fix #3025'` * oltruong for `typo fix #3025'`
* Thomas-S-B for `Removed unnecessary IErrorDetectionStrategy #749` * Thomas-S-B for `Removed unnecessary IErrorDetectionStrategy #749`

View File

@@ -17,10 +17,12 @@ expressly granted herein, whether by implication, estoppel or otherwise.
chokidar: https://github.com/paulmillr/chokidar chokidar: https://github.com/paulmillr/chokidar
comment-json: https://github.com/kaelzhang/node-comment-json comment-json: https://github.com/kaelzhang/node-comment-json
core-js: https://github.com/zloirock/core-js core-js: https://github.com/zloirock/core-js
decompress: https://github.com/kevva/decompress
emmet: https://github.com/emmetio/emmet emmet: https://github.com/emmetio/emmet
error-ex: https://github.com/Qix-/node-error-ex error-ex: https://github.com/Qix-/node-error-ex
escape-string-regexp: https://github.com/sindresorhus/escape-string-regexp escape-string-regexp: https://github.com/sindresorhus/escape-string-regexp
fast-plist: https://github.com/Microsoft/node-fast-plist fast-plist: https://github.com/Microsoft/node-fast-plist
figures: https://github.com/sindresorhus/figures
find-remove: https://www.npmjs.com/package/find-remove find-remove: https://www.npmjs.com/package/find-remove
fs-extra: https://github.com/jprichardson/node-fs-extra fs-extra: https://github.com/jprichardson/node-fs-extra
gc-signals: https://github.com/Microsoft/node-gc-signals gc-signals: https://github.com/Microsoft/node-gc-signals
@@ -41,22 +43,28 @@ expressly granted herein, whether by implication, estoppel or otherwise.
native-keymap: https://github.com/Microsoft/node-native-keymap native-keymap: https://github.com/Microsoft/node-native-keymap
native-watchdog: https://github.com/Microsoft/node-native-watchdog native-watchdog: https://github.com/Microsoft/node-native-watchdog
ng2-charts: https://github.com/valor-software/ng2-charts ng2-charts: https://github.com/valor-software/ng2-charts
node-fetch: https://github.com/bitinn/node-fetch
node-pty: https://github.com/Tyriar/node-pty node-pty: https://github.com/Tyriar/node-pty
nsfw: https://github.com/Axosoft/nsfw nsfw: https://github.com/Axosoft/nsfw
pretty-data: https://github.com/vkiryukhin/pretty-data pretty-data: https://github.com/vkiryukhin/pretty-data
primeng: https://github.com/primefaces/primeng primeng: https://github.com/primefaces/primeng
process-nextick-args: https://github.com/calvinmetcalf/process-nextick-args
pty.js: https://github.com/chjj/pty.js pty.js: https://github.com/chjj/pty.js
reflect-metadata: https://github.com/rbuckton/reflect-metadata reflect-metadata: https://github.com/rbuckton/reflect-metadata
request: https://github.com/request/request
rxjs: https://github.com/ReactiveX/RxJS rxjs: https://github.com/ReactiveX/RxJS
semver: https://github.com/npm/node-semver semver: https://github.com/npm/node-semver
slickgrid: https://github.com/6pac/SlickGrid slickgrid: https://github.com/6pac/SlickGrid
sqltoolsservice: https://github.com/Microsoft/sqltoolsservice sqltoolsservice: https://github.com/Microsoft/sqltoolsservice
svg.js: https://github.com/svgdotjs/svg.js svg.js: https://github.com/svgdotjs/svg.js
systemjs: https://github.com/systemjs/systemjs systemjs: https://github.com/systemjs/systemjs
temp-write: https://github.com/sindresorhus/temp-write
underscore: https://github.com/jashkenas/underscore underscore: https://github.com/jashkenas/underscore
v8-profiler: https://github.com/node-inspector/v8-profiler v8-profiler: https://github.com/node-inspector/v8-profiler
vscode: https://github.com/microsoft/vscode vscode: https://github.com/microsoft/vscode
vscode-debugprotocol: https://github.com/Microsoft/vscode-debugadapter-node vscode-debugprotocol: https://github.com/Microsoft/vscode-debugadapter-node
vscode-languageclient: https://github.com/Microsoft/vscode-languageserver-node
vscode-nls: https://github.com/Microsoft/vscode-nls
vscode-ripgrep: https://github.com/roblourens/vscode-ripgrep vscode-ripgrep: https://github.com/roblourens/vscode-ripgrep
vscode-textmate: https://github.com/Microsoft/vscode-textmate vscode-textmate: https://github.com/Microsoft/vscode-textmate
winreg: https://github.com/fresc81/node-winreg winreg: https://github.com/fresc81/node-winreg
@@ -64,10 +72,9 @@ expressly granted herein, whether by implication, estoppel or otherwise.
yauzl: https://github.com/thejoshwolfe/yauzl yauzl: https://github.com/thejoshwolfe/yauzl
zone.js: https://www.npmjs.com/package/zone zone.js: https://www.npmjs.com/package/zone
Microsoft PROSE SDK: https://microsoft.github.io/prose
%% angular NOTICES AND INFORMATION BEGIN HERE %% angular NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License
Copyright (c) 2014-2017 Google, Inc. http://angular.io Copyright (c) 2014-2017 Google, Inc. http://angular.io
@@ -293,6 +300,20 @@ THE SOFTWARE.
========================================= =========================================
END OF core-js NOTICES AND INFORMATION END OF core-js NOTICES AND INFORMATION
%% decompress NOTICES AND INFORMATION BEGIN HERE
=========================================
MIT License
Copyright (c) Kevin Mårtensson <kevinmartensson@gmail.com> (github.com/kevva)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=========================================
END OF decompress NOTICES AND INFORMATION
%% emmet NOTICES AND INFORMATION BEGIN HERE %% emmet NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
The MIT License (MIT) The MIT License (MIT)
@@ -394,6 +415,20 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL
========================================= =========================================
END OF fast-plist NOTICES AND INFORMATION END OF fast-plist NOTICES AND INFORMATION
%% figures NOTICES AND INFORMATION BEGIN HERE
=========================================
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=========================================
END OF figures NOTICES AND INFORMATION
%% fs-extra NOTICES AND INFORMATION BEGIN HERE %% fs-extra NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
(The MIT License) (The MIT License)
@@ -1335,6 +1370,32 @@ SOFTWARE.
========================================= =========================================
END OF ng2-charts NOTICES AND INFORMATION END OF ng2-charts NOTICES AND INFORMATION
%% node-fetch NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
Copyright (c) 2016 David Frank
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=========================================
END OF node-fetch NOTICES AND INFORMATION
%% node-pty NOTICES AND INFORMATION BEGIN HERE %% node-pty NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/) Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/)
@@ -1409,6 +1470,30 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
========================================= =========================================
END OF primeng NOTICES AND INFORMATION END OF primeng NOTICES AND INFORMATION
%% process-nextick-args NOTICES AND INFORMATION BEGIN HERE
=========================================
# Copyright (c) 2015 Calvin Metcalf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.**
=========================================
END OF process-nextick-args NOTICES AND INFORMATION
%% pty.js NOTICES AND INFORMATION BEGIN HERE %% pty.js NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/) Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/)
@@ -1493,6 +1578,66 @@ END OF TERMS AND CONDITIONS
========================================= =========================================
END OF reflect-metadata NOTICES AND INFORMATION END OF reflect-metadata NOTICES AND INFORMATION
%% request NOTICES AND INFORMATION BEGIN HERE
=========================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
=========================================
END OF request NOTICES AND INFORMATION
%% rxjs NOTICES AND INFORMATION BEGIN HERE %% rxjs NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
Apache License Apache License
@@ -1818,6 +1963,20 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL
========================================= =========================================
END OF systemjs NOTICES AND INFORMATION END OF systemjs NOTICES AND INFORMATION
%% temp-write NOTICES AND INFORMATION BEGIN HERE
=========================================
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=========================================
END OF temp-write NOTICES AND INFORMATION
%% underscore NOTICES AND INFORMATION BEGIN HERE %% underscore NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
Copyright (c) 2009-2017 Jeremy Ashkenas, DocumentCloud and Investigative Copyright (c) 2009-2017 Jeremy Ashkenas, DocumentCloud and Investigative
@@ -1920,6 +2079,50 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
========================================= =========================================
END OF vscode-debugprotocol NOTICES AND INFORMATION END OF vscode-debugprotocol NOTICES AND INFORMATION
%% vscode-languageclient NOTICES AND INFORMATION BEGIN HERE
=========================================
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=========================================
END OF vscode-languageclient NOTICES AND INFORMATION
%% vscode-nls NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
Copyright (c) Microsoft Corporation
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=========================================
END OF vscode-nls NOTICES AND INFORMATION
%% vscode-ripgrep NOTICES AND INFORMATION BEGIN HERE %% vscode-ripgrep NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
vscode-ripgrep vscode-ripgrep
@@ -2079,3 +2282,188 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
========================================= =========================================
END OF zone.js NOTICES AND INFORMATION END OF zone.js NOTICES AND INFORMATION
%% Microsoft.ProgramSynthesis.Common NOTICES AND INFORMATION BEGIN HERE
=========================================
NOTICES AND INFORMATION
Do Not Translate or Localize
This software incorporates material from third parties. Microsoft makes certain
open source code available at http://3rdpartysource.microsoft.com, or you may
send a check or money order for US $5.00, including the product name, the open
source component name, and version number, to:
Source Code Compliance Team
Microsoft Corporation
One Microsoft Way
Redmond, WA 98052
USA
Notwithstanding any other terms, you may reverse engineer this software to the
extent required to debug changes to any libraries licensed under the GNU Lesser
General Public License.
-------------------------------START OF THIRD-PARTY NOTICES-------------------------------------------
===================================CoreFx (BEGIN)
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
===================================CoreFx (END)
===================================CoreFxLab (BEGIN)
The MIT License (MIT)
Copyright (c) Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
===================================CoreFxLab (END)
===================================Reactive Extensions (BEGIN)
Copyright (c) .NET Foundation and Contributors
All Rights Reserved
Licensed under the Apache License, Version 2.0 (the "License"); you
may not use this file except in compliance with the License. You may
obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing permissions
and limitations under the License.
List of contributors to the Rx libraries
Rx and Ix.NET:
Wes Dyer
Jeffrey van Gogh
Matthew Podwysocki
Bart De Smet
Danny van Velzen
Erik Meijer
Brian Beckman
Aaron Lahman
Georgi Chkodrov
Arthur Watson
Gert Drapers
Mark Shields
Eric Rozell
Rx.js and Ix.js:
Matthew Podwysocki
Jeffrey van Gogh
Bart De Smet
Brian Beckman
Wes Dyer
Erik Meijer
Tx:
Georgi Chkodrov
Bart De Smet
Aaron Lahman
Erik Meijer
Brian Grunkemeyer
Beysim Sezgin
Tiho Tarnavski
Collin Meek
Sajay Anthony
Karen Albrecht
John Allen
Zach Kramer
Rx++ and Ix++:
Aaron Lahman
===================================Reactive Extensions (END)
-------------------------------END OF THIRD-PARTY NOTICES-------------------------------------------
=========================================
END OF Microsoft.ProgramSynthesis.Common NOTICES AND INFORMATION
%% Microsoft.ProgramSynthesis.Detection NOTICES AND INFORMATION BEGIN HERE
=========================================
NOTICES AND INFORMATION
Do Not Translate or Localize
This software incorporates material from third parties. Microsoft makes certain
open source code available at http://3rdpartysource.microsoft.com, or you may
send a check or money order for US $5.00, including the product name, the open
source component name, and version number, to:
Source Code Compliance Team
Microsoft Corporation
One Microsoft Way
Redmond, WA 98052
USA
Notwithstanding any other terms, you may reverse engineer this software to the
extent required to debug changes to any libraries licensed under the GNU Lesser
General Public License.
-------------------------------START OF THIRD-PARTY NOTICES-------------------------------------------
===================================ExcelDataReader (BEGIN)
The MIT License (MIT)
Copyright (c) 2014 ExcelDataReader
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
===================================ExcelDataReader (END)
-------------------------------END OF THIRD-PARTY NOTICES-------------------------------------------
=========================================
END OF Microsoft.ProgramSynthesis.Detection NOTICES AND INFORMATION

View File

@@ -12,9 +12,13 @@ steps:
displayName: 'preinstall' displayName: 'preinstall'
- script: | - script: |
export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0 export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:10
sh -e /etc/init.d/xvfb start sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
sleep 3 sudo chmod +x /etc/init.d/xvfb
sudo update-rc.d xvfb defaults
sudo service xvfb start
# sh -e /etc/init.d/xvfb start
# sleep 3
displayName: 'Linux preinstall' displayName: 'Linux preinstall'
condition: eq(variables['Agent.OS'], 'Linux') condition: eq(variables['Agent.OS'], 'Linux')
@@ -23,13 +27,13 @@ steps:
displayName: 'Install' displayName: 'Install'
- script: | - script: |
node_modules/.bin/gulp electron --silent node_modules/.bin/gulp electron
node_modules/.bin/gulp compile --silent --max_old_space_size=4096 node_modules/.bin/gulp compile --max_old_space_size=4096
node_modules/.bin/gulp optimize-vscode --silent --max_old_space_size=4096 node_modules/.bin/gulp optimize-vscode --max_old_space_size=4096
displayName: 'Scripts' displayName: 'Scripts'
- script: | - script: |
./scripts/test.sh --reporter mocha-junit-reporter DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
displayName: 'Tests' displayName: 'Tests'
- task: PublishTestResults@2 - task: PublishTestResults@2

View File

@@ -3,10 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
const cp = require('child_process'); import * as cp from 'child_process';
function yarnInstall(package: string): void { function yarnInstall(packageName: string): void {
cp.execSync(`yarn add --no-lockfile ${package}`); cp.execSync(`yarn add --no-lockfile ${packageName}`);
} }
const product = require('../../../product.json'); const product = require('../../../product.json');

View File

@@ -44,7 +44,7 @@ function createDefaultConfig(quality: string): Config {
} }
function getConfig(quality: string): Promise<Config> { function getConfig(quality: string): Promise<Config> {
const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT'], { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
const collection = 'dbs/builds/colls/config'; const collection = 'dbs/builds/colls/config';
const query = { const query = {
query: `SELECT TOP 1 * FROM c WHERE c.id = @quality`, query: `SELECT TOP 1 * FROM c WHERE c.id = @quality`,
@@ -66,7 +66,8 @@ interface Asset {
platform: string; platform: string;
type: string; type: string;
url: string; url: string;
mooncakeUrl: string; // {{SQL CARBON EDIT}}
mooncakeUrl: string | undefined;
hash: string; hash: string;
sha256hash: string; sha256hash: string;
size: number; size: number;
@@ -74,7 +75,7 @@ interface Asset {
} }
function createOrUpdate(commit: string, quality: string, platform: string, type: string, release: NewDocument, asset: Asset, isUpdate: boolean): Promise<void> { function createOrUpdate(commit: string, quality: string, platform: string, type: string, release: NewDocument, asset: Asset, isUpdate: boolean): Promise<void> {
const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT'], { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] }); const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
const collection = 'dbs/builds/colls/' + quality; const collection = 'dbs/builds/colls/' + quality;
const updateQuery = { const updateQuery = {
query: 'SELECT TOP 1 * FROM c WHERE c.id = @id', query: 'SELECT TOP 1 * FROM c WHERE c.id = @id',
@@ -128,7 +129,7 @@ async function assertContainer(blobService: azure.BlobService, quality: string):
await new Promise((c, e) => blobService.createContainerIfNotExists(quality, { publicAccessLevel: 'blob' }, err => err ? e(err) : c())); await new Promise((c, e) => blobService.createContainerIfNotExists(quality, { publicAccessLevel: 'blob' }, err => err ? e(err) : c()));
} }
async function doesAssetExist(blobService: azure.BlobService, quality: string, blobName: string): Promise<boolean> { async function doesAssetExist(blobService: azure.BlobService, quality: string, blobName: string): Promise<boolean | undefined> {
const existsResult = await new Promise<azure.BlobService.BlobResult>((c, e) => blobService.doesBlobExist(quality, blobName, (err, r) => err ? e(err) : c(r))); const existsResult = await new Promise<azure.BlobService.BlobResult>((c, e) => blobService.doesBlobExist(quality, blobName, (err, r) => err ? e(err) : c(r)));
return existsResult.exists; return existsResult.exists;
} }
@@ -151,8 +152,8 @@ interface PublishOptions {
async function publish(commit: string, quality: string, platform: string, type: string, name: string, version: string, _isUpdate: string, file: string, opts: PublishOptions): Promise<void> { async function publish(commit: string, quality: string, platform: string, type: string, name: string, version: string, _isUpdate: string, file: string, opts: PublishOptions): Promise<void> {
const isUpdate = _isUpdate === 'true'; const isUpdate = _isUpdate === 'true';
const queuedBy = process.env['BUILD_QUEUEDBY']; const queuedBy = process.env['BUILD_QUEUEDBY']!;
const sourceBranch = process.env['BUILD_SOURCEBRANCH']; const sourceBranch = process.env['BUILD_SOURCEBRANCH']!;
const isReleased = quality === 'insider' const isReleased = quality === 'insider'
&& /^master$|^refs\/heads\/master$/.test(sourceBranch) && /^master$|^refs\/heads\/master$/.test(sourceBranch)
&& /Project Collection Service Accounts|Microsoft.VisualStudio.Services.TFS/.test(queuedBy); && /Project Collection Service Accounts|Microsoft.VisualStudio.Services.TFS/.test(queuedBy);
@@ -180,9 +181,9 @@ async function publish(commit: string, quality: string, platform: string, type:
console.log('SHA256:', sha256hash); console.log('SHA256:', sha256hash);
const blobName = commit + '/' + name; const blobName = commit + '/' + name;
const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']; const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']!;
const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']) const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
.withFilter(new azure.ExponentialRetryPolicyFilter(20)); .withFilter(new azure.ExponentialRetryPolicyFilter(20));
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
@@ -198,7 +199,7 @@ async function publish(commit: string, quality: string, platform: string, type:
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
if (process.env['MOONCAKE_STORAGE_ACCESS_KEY']) { if (process.env['MOONCAKE_STORAGE_ACCESS_KEY']) {
const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY'], `${storageAccount}.blob.core.chinacloudapi.cn`) const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`)
.withFilter(new azure.ExponentialRetryPolicyFilter(20)); .withFilter(new azure.ExponentialRetryPolicyFilter(20));
// mooncake is fussy and far away, this is needed! // mooncake is fussy and far away, this is needed!
@@ -214,7 +215,7 @@ async function publish(commit: string, quality: string, platform: string, type:
doesAssetExist(mooncakeBlobService, quality, blobName) doesAssetExist(mooncakeBlobService, quality, blobName)
]); ]);
const promises = []; const promises: Array<Promise<void>> = [];
if (!blobExists) { if (!blobExists) {
promises.push(uploadBlob(blobService, quality, blobName, file)); promises.push(uploadBlob(blobService, quality, blobName, file));
@@ -227,7 +228,6 @@ async function publish(commit: string, quality: string, platform: string, type:
console.log('Skipping Mooncake publishing.'); console.log('Skipping Mooncake publishing.');
} }
if (promises.length === 0) { if (promises.length === 0) {
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`); console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
return; return;
@@ -268,7 +268,7 @@ async function publish(commit: string, quality: string, platform: string, type:
isReleased: config.frozen ? false : isReleased, isReleased: config.frozen ? false : isReleased,
sourceBranch, sourceBranch,
queuedBy, queuedBy,
assets: [], assets: [] as Array<Asset>,
updates: {} as any updates: {} as any
}; };
@@ -284,6 +284,11 @@ async function publish(commit: string, quality: string, platform: string, type:
} }
function main(): void { function main(): void {
if (process.env['VSCODE_BUILD_SKIP_PUBLISH']) {
console.warn('Skipping publish due to VSCODE_BUILD_SKIP_PUBLISH');
return;
}
const opts = minimist<PublishOptions>(process.argv.slice(2), { const opts = minimist<PublishOptions>(process.argv.slice(2), {
boolean: ['upload-only'] boolean: ['upload-only']
}); });

View File

@@ -97,7 +97,7 @@ function updateVersion(accessor: IVersionAccessor, symbolsPath: string) {
function asyncRequest<T>(options: request.UrlOptions & request.CoreOptions): Promise<T> { function asyncRequest<T>(options: request.UrlOptions & request.CoreOptions): Promise<T> {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
request(options, (error, response, body) => { request(options, (error, _response, body) => {
if (error) { if (error) {
reject(error); reject(error);
} else { } else {
@@ -107,17 +107,17 @@ function asyncRequest<T>(options: request.UrlOptions & request.CoreOptions): Pro
}); });
} }
function downloadAsset(repository, assetName: string, targetPath: string, electronVersion: string) { function downloadAsset(repository: any, assetName: string, targetPath: string, electronVersion: string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
repository.getReleases({ tag_name: `v${electronVersion}` }, (err, releases) => { repository.getReleases({ tag_name: `v${electronVersion}` }, (err: any, releases: any) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
const asset = releases[0].assets.filter(asset => asset.name === assetName)[0]; const asset = releases[0].assets.filter((asset: any) => asset.name === assetName)[0];
if (!asset) { if (!asset) {
reject(new Error(`Asset with name ${assetName} not found`)); reject(new Error(`Asset with name ${assetName} not found`));
} else { } else {
repository.downloadAsset(asset, (err, reader) => { repository.downloadAsset(asset, (err: any, reader: any) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
@@ -156,7 +156,7 @@ async function ensureVersionAndSymbols(options: IOptions) {
const symbolsName = symbolsZipName(options.platform, options.versions.electron, options.versions.insiders); const symbolsName = symbolsZipName(options.platform, options.versions.electron, options.versions.insiders);
const symbolsPath = await tmpFile('symbols.zip'); const symbolsPath = await tmpFile('symbols.zip');
console.log(`HockeyApp: downloading symbols ${symbolsName} for electron ${options.versions.electron} (${options.platform}) into ${symbolsPath}`); console.log(`HockeyApp: downloading symbols ${symbolsName} for electron ${options.versions.electron} (${options.platform}) into ${symbolsPath}`);
await downloadAsset(new github({ repo: options.repository, token: options.access.githubToken }), symbolsName, symbolsPath, options.versions.electron); await downloadAsset(new (github as any)({ repo: options.repository, token: options.access.githubToken }), symbolsName, symbolsPath, options.versions.electron);
// Create version // Create version
console.log(`HockeyApp: creating new version ${options.versions.code} (${options.platform})`); console.log(`HockeyApp: creating new version ${options.versions.code} (${options.platform})`);

View File

@@ -0,0 +1,40 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- script: |
yarn
displayName: Install Dependencies
- script: |
yarn gulp electron-x64
displayName: Download Electron
- script: |
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: |
yarn monaco-compile-check
displayName: Run Monaco Editor Checks
- script: |
yarn strict-null-check
displayName: Run Strict Null Checks
- script: |
yarn compile
displayName: Compile Sources
- script: |
yarn download-builtin-extensions
displayName: Download Built-in Extensions
- script: |
./scripts/test.sh --tfs "Unit Tests"
displayName: Run Unit Tests
- script: |
./scripts/test-integration.sh --tfs "Integration Tests"
displayName: Run Integration Tests
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
testResultsFiles: '*-results.xml'
searchFolder: '$(Build.ArtifactStagingDirectory)/test-results'
condition: succeededOrFailed()

View File

@@ -0,0 +1,91 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- script: |
set -e
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
yarn
yarn gulp -- hygiene
yarn monaco-compile-check
yarn strict-null-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" yarn gulp -- mixin
node build/azure-pipelines/common/installDistro.js
node build/lib/builtInExtensions.js
displayName: Prepare build
- script: |
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- vscode-darwin-min upload-vscode-sourcemaps
displayName: Build
- script: |
set -e
./scripts/test.sh --build --tfs "Unit Tests"
# APP_NAME="`ls $(agent.builddirectory)/VSCode-darwin | head -n 1`"
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME"
displayName: Run unit tests
- script: |
set -e
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd
displayName: Archive build
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)'
Pattern: 'VSCode-darwin.zip'
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-401337-Apple",
"operationSetCode": "MacAppDeveloperSign",
"parameters": [ ],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
displayName: Codesign
- script: |
set -e
# remove pkg from archive
zip -d ../VSCode-darwin.zip "*.pkg"
# publish the build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js \
"$(VSCODE_QUALITY)" \
darwin \
archive \
"VSCode-darwin-$(VSCODE_QUALITY).zip" \
$VERSION \
true \
../VSCode-darwin.zip
# publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)"
# upload configuration
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- upload-vscode-configuration
displayName: Publish
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
continueOnError: true

View File

@@ -0,0 +1 @@
pat

View File

@@ -0,0 +1,45 @@
steps:
- script: |
set -e
sudo apt-get update
sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 libgconf-2-4 dbus xvfb libgtk-3-0
sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
sudo chmod +x /etc/init.d/xvfb
sudo update-rc.d xvfb defaults
sudo service xvfb start
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- script: |
yarn
displayName: Install Dependencies
- script: |
yarn gulp electron-x64
displayName: Download Electron
- script: |
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: |
yarn monaco-compile-check
displayName: Run Monaco Editor Checks
- script: |
yarn strict-null-check
displayName: Run Strict Null Checks
- script: |
yarn compile
displayName: Compile Sources
- script: |
yarn download-builtin-extensions
displayName: Download Built-in Extensions
- script: |
DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests"
displayName: Run Unit Tests
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
testResultsFiles: '*-results.xml'
searchFolder: '$(Build.ArtifactStagingDirectory)/test-results'
condition: succeededOrFailed()

View File

@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const documentdb_1 = require("documentdb");
function createDefaultConfig(quality) {
return {
id: quality,
frozen: false
};
}
function getConfig(quality) {
const client = new documentdb_1.DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT'], { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
const collection = 'dbs/builds/colls/config';
const query = {
query: `SELECT TOP 1 * FROM c WHERE c.id = @quality`,
parameters: [
{ name: '@quality', value: quality }
]
};
return new Promise((c, e) => {
client.queryDocuments(collection, query).toArray((err, results) => {
if (err && err.code !== 409) {
return e(err);
}
c(!results || results.length === 0 ? createDefaultConfig(quality) : results[0]);
});
});
}
getConfig(process.argv[2])
.then(config => {
console.log(config.frozen);
process.exit(0);
})
.catch(err => {
console.error(err);
process.exit(1);
});

View File

@@ -0,0 +1,112 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- script: |
set -e
export npm_config_arch="$(VSCODE_ARCH)"
if [[ "$(VSCODE_ARCH)" == "ia32" ]]; then
export PKG_CONFIG_PATH="/usr/lib/i386-linux-gnu/pkgconfig"
fi
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
CHILD_CONCURRENCY=1 yarn
npm run gulp -- hygiene
npm run monaco-compile-check
npm run strict-null-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
node build/azure-pipelines/common/installDistro.js
node build/lib/builtInExtensions.js
- script: |
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min
name: build
- script: |
set -e
npm run gulp -- "electron-$(VSCODE_ARCH)"
# xvfb seems to be crashing often, let's make sure it's always up
service xvfb start
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests"
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
name: test
- script: |
set -e
REPO="$(pwd)"
ROOT="$REPO/.."
ARCH="$(VSCODE_ARCH)"
# Publish tarball
PLATFORM_LINUX="linux-$(VSCODE_ARCH)"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
BUILDNAME="VSCode-$PLATFORM_LINUX"
BUILD="$ROOT/$BUILDNAME"
BUILD_VERSION="$(date +%s)"
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
PACKAGEJSON="$BUILD/resources/app/package.json"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
rm -rf $ROOT/code-*.tar.*
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
# Publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)"
# Publish DEB
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
PLATFORM_DEB="linux-deb-$ARCH"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
# Publish RPM
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
PLATFORM_RPM="linux-rpm-$ARCH"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
# Publish Snap
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-prepare-snap"
# Pack snap tarball artifact, in order to preserve file perms
mkdir -p $REPO/.build/linux/snap-tarball
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz"
rm -rf $SNAP_TARBALL_PATH
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
continueOnError: true
- task: PublishPipelineArtifact@0
displayName: 'Publish Pipeline Artifact'
inputs:
artifactName: snap-$(VSCODE_ARCH)
targetPath: .build/linux/snap-tarball

View File

@@ -0,0 +1,42 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- task: DownloadPipelineArtifact@0
displayName: 'Download Pipeline Artifact'
inputs:
artifactName: snap-$(VSCODE_ARCH)
targetPath: .build/linux/snap-tarball
- script: |
set -e
REPO="$(pwd)"
ARCH="$(VSCODE_ARCH)"
SNAP_ROOT="$REPO/.build/linux/snap/$ARCH"
# Install build dependencies
(cd build && yarn)
# Unpack snap tarball artifact, in order to preserve file perms
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$ARCH.tar.gz"
(cd .build/linux && tar -xzf $SNAP_TARBALL_PATH)
# Create snap package
BUILD_VERSION="$(date +%s)"
SNAP_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.snap"
PACKAGEJSON="$(ls $SNAP_ROOT/code*/usr/share/code*/resources/app/package.json)"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
SNAP_PATH="$SNAP_ROOT/$SNAP_FILENAME"
(cd $SNAP_ROOT/code-* && snapcraft snap --output "$SNAP_PATH")
# Publish snap package
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"

View File

@@ -0,0 +1,65 @@
resources:
containers:
- container: vscode-x64
image: joaomoreno/vscode-linux-build-agent:x64
- container: vscode-ia32
image: joaomoreno/vscode-linux-build-agent:ia32
- container: snapcraft
image: snapcore/snapcraft
jobs:
- job: Windows
condition: eq(variables['VSCODE_BUILD_WIN32'], 'true')
pool:
vmImage: VS2017-Win2016
variables:
VSCODE_ARCH: x64
steps:
- template: win32/product-build-win32.yml
- job: Windows32
condition: eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true')
pool:
vmImage: VS2017-Win2016
variables:
VSCODE_ARCH: ia32
steps:
- template: win32/product-build-win32.yml
- job: Linux
condition: eq(variables['VSCODE_BUILD_LINUX'], 'true')
pool:
vmImage: 'Ubuntu-16.04'
variables:
VSCODE_ARCH: x64
container: vscode-x64
steps:
- template: linux/product-build-linux.yml
- job: LinuxSnap
condition: eq(variables['VSCODE_BUILD_LINUX'], 'true')
pool:
vmImage: 'Ubuntu-16.04'
variables:
VSCODE_ARCH: x64
container: snapcraft
dependsOn: Linux
steps:
- template: linux/snap-build-linux.yml
- job: Linux32
condition: eq(variables['VSCODE_BUILD_LINUX_32BIT'], 'true')
pool:
vmImage: 'Ubuntu-16.04'
variables:
VSCODE_ARCH: ia32
container: vscode-ia32
steps:
- template: linux/product-build-linux.yml
- job: macOS
condition: eq(variables['VSCODE_BUILD_MACOS'], 'true')
pool:
vmImage: macOS 10.13
steps:
- template: darwin/product-build-darwin.yml

View File

@@ -0,0 +1,44 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- task: UsePythonVersion@0
inputs:
versionSpec: '2.x'
addToPath: true
- powershell: |
yarn
displayName: Install Dependencies
- powershell: |
yarn gulp electron
displayName: Download Electron
- powershell: |
yarn gulp hygiene
displayName: Run Hygiene Checks
- powershell: |
yarn monaco-compile-check
displayName: Run Monaco Editor Checks
- script: |
yarn strict-null-check
displayName: Run Strict Null Checks
- powershell: |
yarn compile
displayName: Compile Sources
- powershell: |
yarn download-builtin-extensions
displayName: Download Built-in Extensions
- powershell: |
.\scripts\test.bat --tfs "Unit Tests"
displayName: Run Unit Tests
- powershell: |
.\scripts\test-integration.bat --tfs "Integration Tests"
displayName: Run Integration Tests
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
testResultsFiles: '*-results.xml'
searchFolder: '$(Build.ArtifactStagingDirectory)/test-results'
condition: succeededOrFailed()

View File

@@ -0,0 +1,152 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.12.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- task: UsePythonVersion@0
inputs:
versionSpec: '2.x'
addToPath: true
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
"machine monacotools.visualstudio.com password $(VSO_PAT)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
$env:npm_config_arch="$(VSCODE_ARCH)"
$env:CHILD_CONCURRENCY="1"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
exec { yarn }
exec { npm run gulp -- hygiene }
exec { npm run monaco-compile-check }
exec { npm run strict-null-check }
exec { npm run gulp -- mixin }
exec { node build/azure-pipelines/common/installDistro.js }
exec { node build/lib/builtInExtensions.js }
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" }
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-inno-updater" }
name: build
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp -- "electron-$(VSCODE_ARCH)" }
exec { .\scripts\test.bat --build --tfs "Unit Tests" }
# yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
name: test
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)'
Pattern: '*.dll,*.exe,*.node'
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "VS Code"
},
{
"parameterName": "OpusInfo",
"parameterValue": "https://code.visualstudio.com/"
},
{
"parameterName": "Append",
"parameterValue": "/as"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolVerify",
"parameters": [
{
"parameterName": "VerifyAll",
"parameterValue": "/all"
}
],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
- task: NuGetCommand@2
displayName: Install ESRPClient.exe
inputs:
restoreSolution: 'build\azure-pipelines\win32\ESRPClient\packages.config'
feedsToUse: config
nugetConfigPath: 'build\azure-pipelines\win32\ESRPClient\NuGet.config'
externalFeedCredentials: 3fc0b7f7-da09-4ae7-a9c8-d69824b1819b
restoreDirectory: packages
- task: ESRPImportCertTask@1
displayName: Import ESRP Request Signing Certificate
inputs:
ESRP: 'ESRP CodeSign'
- powershell: |
$ErrorActionPreference = "Stop"
.\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 -AuthCertificateBase64 $(ESRP_AUTH_CERTIFICATE) -AuthCertificateKey $(ESRP_AUTH_CERTIFICATE_KEY)
displayName: Import ESRP Auth Certificate
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-system-setup" "vscode-win32-$(VSCODE_ARCH)-user-setup" --sign }
$Repo = "$(pwd)"
$Root = "$Repo\.."
$SystemExe = "$Repo\.build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup.exe"
$UserExe = "$Repo\.build\win32-$(VSCODE_ARCH)\user-setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip"
$Build = "$Root\VSCode-win32-$(VSCODE_ARCH)"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
$env:MOONCAKE_STORAGE_ACCESS_KEY = "$(MOONCAKE_STORAGE_ACCESS_KEY)"
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
$assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $SystemExe }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-user" setup "VSCodeUserSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $UserExe }
# publish hockeyapp symbols
$hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" }
exec { node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId }
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
continueOnError: true

View File

@@ -0,0 +1,70 @@
function Create-TmpJson($Obj) {
$FileName = [System.IO.Path]::GetTempFileName()
ConvertTo-Json -Depth 100 $Obj | Out-File -Encoding UTF8 $FileName
return $FileName
}
$Auth = Create-TmpJson @{
Version = "1.0.0"
AuthenticationType = "AAD_CERT"
ClientId = $env:ESRPClientId
AuthCert = @{
SubjectName = $env:ESRPAuthCertificateSubjectName
StoreLocation = "LocalMachine"
StoreName = "My"
}
RequestSigningCert = @{
SubjectName = $env:ESRPCertificateSubjectName
StoreLocation = "LocalMachine"
StoreName = "My"
}
}
$Policy = Create-TmpJson @{
Version = "1.0.0"
}
$Input = Create-TmpJson @{
Version = "1.0.0"
SignBatches = @(
@{
SourceLocationType = "UNC"
SignRequestFiles = @(
@{
SourceLocation = $args[0]
}
)
SigningInfo = @{
Operations = @(
@{
KeyCode = "CP-230012"
OperationCode = "SigntoolSign"
Parameters = @{
OpusName = "VS Code"
OpusInfo = "https://code.visualstudio.com/"
Append = "/as"
FileDigest = "/fd `"SHA256`""
PageHash = "/NPH"
TimeStamp = "/tr `"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer`" /td sha256"
}
ToolName = "sign"
ToolVersion = "1.0"
},
@{
KeyCode = "CP-230012"
OperationCode = "SigntoolVerify"
Parameters = @{
VerifyAll = "/all"
}
ToolName = "sign"
ToolVersion = "1.0"
}
)
}
}
)
}
$Output = [System.IO.Path]::GetTempFileName()
$ScriptPath = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
& "$ScriptPath\ESRPClient\packages\EsrpClient.1.0.27\tools\ESRPClient.exe" Sign -a $Auth -p $Policy -i $Input -o $Output

View File

@@ -1,12 +1,2 @@
[ [
{
"name": "ms-vscode.node-debug",
"version": "1.26.7",
"repo": "https://github.com/Microsoft/vscode-node-debug"
},
{
"name": "ms-vscode.node-debug2",
"version": "1.26.8",
"repo": "https://github.com/Microsoft/vscode-node-debug2"
}
] ]

View File

@@ -43,7 +43,7 @@ function asYarnDependency(prefix, tree) {
} }
function getYarnProductionDependencies(cwd) { function getYarnProductionDependencies(cwd) {
const raw = cp.execSync('yarn list --json', { cwd, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'ignore'] }); const raw = cp.execSync('yarn list --json', { cwd, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'inherit'] });
const match = /^{"type":"tree".*$/m.exec(raw); const match = /^{"type":"tree".*$/m.exec(raw);
if (!match || match.length !== 1) { if (!match || match.length !== 1) {

View File

@@ -28,7 +28,7 @@ var editorEntryPoints = [
name: 'vs/editor/editor.main', name: 'vs/editor/editor.main',
include: [], include: [],
exclude: ['vs/css', 'vs/nls'], exclude: ['vs/css', 'vs/nls'],
prepend: ['out-build/vs/css.js', 'out-build/vs/nls.js'], prepend: ['out-editor-build/vs/css.js', 'out-editor-build/vs/nls.js'],
}, },
{ {
name: 'vs/base/common/worker/simpleWorker', name: 'vs/base/common/worker/simpleWorker',
@@ -79,16 +79,21 @@ gulp.task('extract-editor-src', ['clean-editor-src'], function () {
apiusages, apiusages,
extrausages extrausages
], ],
typings: [
'typings/lib.ie11_safe_es6.d.ts',
'typings/thenable.d.ts',
'typings/es6-promise.d.ts',
'typings/require-monaco.d.ts',
'vs/monaco.d.ts'
],
libs: [ libs: [
`lib.d.ts`, `lib.es5.d.ts`,
`lib.es2015.collection.d.ts` `lib.dom.d.ts`,
`lib.webworker.importscripts.d.ts`
], ],
redirects: { redirects: {
'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock', 'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock',
}, },
compilerOptions: {
module: 2, // ModuleKind.AMD
},
shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers
importIgnorePattern: /^vs\/css!/, importIgnorePattern: /^vs\/css!/,
destRoot: path.join(root, 'out-editor-src') destRoot: path.join(root, 'out-editor-src')
@@ -108,6 +113,8 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-editor-build'],
loaderConfig: { loaderConfig: {
paths: { paths: {
'vs': 'out-editor-build/vs', 'vs': 'out-editor-build/vs',
'vs/css': 'out-editor-build/vs/css.build',
'vs/nls': 'out-editor-build/vs/nls.build',
'vscode': 'empty:' 'vscode': 'empty:'
} }
}, },
@@ -122,25 +129,42 @@ gulp.task('clean-minified-editor', util.rimraf('out-editor-min'));
gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor')); gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor'));
gulp.task('clean-editor-esm', util.rimraf('out-editor-esm')); gulp.task('clean-editor-esm', util.rimraf('out-editor-esm'));
gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro'], function () { gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro', 'extract-editor-src'], function () {
standalone.createESMSourcesAndResources({ standalone.createESMSourcesAndResources2({
entryPoints: [ srcFolder: './out-editor-src',
'vs/editor/editor.main', outFolder: './out-editor-esm',
'vs/editor/editor.worker'
],
outFolder: './out-editor-esm/src',
outResourcesFolder: './out-monaco-editor-core/esm', outResourcesFolder: './out-monaco-editor-core/esm',
redirects: { ignores: [
'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock', 'inlineEntryPoint:0.ts',
'vs/nls': 'vs/nls.mock', 'inlineEntryPoint:1.ts',
'vs/loader.js',
'vs/nls.ts',
'vs/nls.build.js',
'vs/nls.d.ts',
'vs/css.js',
'vs/css.build.js',
'vs/css.d.ts',
'vs/base/worker/workerMain.ts',
],
renames: {
'vs/nls.mock.ts': 'vs/nls.ts'
} }
}); });
}); });
gulp.task('compile-editor-esm', ['extract-editor-esm', 'clean-editor-distro'], function () { gulp.task('compile-editor-esm', ['extract-editor-esm', 'clean-editor-distro'], function () {
const result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], { if (process.platform === 'win32') {
cwd: path.join(__dirname, '../out-editor-esm') const result = cp.spawnSync(`..\\node_modules\\.bin\\tsc.cmd`, {
}); cwd: path.join(__dirname, '../out-editor-esm')
console.log(result.stdout.toString()); });
console.log(result.stdout.toString());
console.log(result.stderr.toString());
} else {
const result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], {
cwd: path.join(__dirname, '../out-editor-esm')
});
console.log(result.stdout.toString());
console.log(result.stderr.toString());
}
}); });
function toExternalDTS(contents) { function toExternalDTS(contents) {
@@ -194,7 +218,7 @@ gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify
this.emit('data', new File({ this.emit('data', new File({
path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'), path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'),
base: data.base, base: data.base,
contents: new Buffer(toExternalDTS(data.contents.toString())) contents: Buffer.from(toExternalDTS(data.contents.toString()))
})); }));
})) }))
.pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')), .pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')),

View File

@@ -21,6 +21,7 @@ const nlsDev = require('vscode-nls-dev');
const root = path.dirname(__dirname); const root = path.dirname(__dirname);
const commit = util.getVersion(root); const commit = util.getVersion(root);
const plumber = require('gulp-plumber'); const plumber = require('gulp-plumber');
const _ = require('underscore');
const extensionsPath = path.join(path.dirname(__dirname), 'extensions'); const extensionsPath = path.join(path.dirname(__dirname), 'extensions');
@@ -35,7 +36,8 @@ const tasks = compilations.map(function (tsconfigFile) {
const absolutePath = path.join(extensionsPath, tsconfigFile); const absolutePath = path.join(extensionsPath, tsconfigFile);
const relativeDirname = path.dirname(tsconfigFile); const relativeDirname = path.dirname(tsconfigFile);
const tsOptions = require(absolutePath).compilerOptions; const tsconfig = require(absolutePath);
const tsOptions = _.assign({}, tsconfig.extends ? require(path.join(extensionsPath, relativeDirname, tsconfig.extends)).compilerOptions : {}, tsconfig.compilerOptions);
tsOptions.verbose = false; tsOptions.verbose = false;
tsOptions.sourceMap = true; tsOptions.sourceMap = true;
@@ -167,4 +169,4 @@ gulp.task('watch-extensions', tasks.map(t => t.watch));
gulp.task('clean-extensions-build', tasks.map(t => t.cleanBuild)); gulp.task('clean-extensions-build', tasks.map(t => t.cleanBuild));
gulp.task('compile-extensions-build', tasks.map(t => t.compileBuild)); gulp.task('compile-extensions-build', tasks.map(t => t.compileBuild));
gulp.task('watch-extensions-build', tasks.map(t => t.watchBuild)); gulp.task('watch-extensions-build', tasks.map(t => t.watchBuild));

View File

@@ -43,8 +43,11 @@ const indentationFilter = [
// except specific files // except specific files
'!ThirdPartyNotices.txt', '!ThirdPartyNotices.txt',
'!LICENSE.txt', '!LICENSE.txt',
'!**/LICENSE',
'!src/vs/nls.js', '!src/vs/nls.js',
'!src/vs/nls.build.js',
'!src/vs/css.js', '!src/vs/css.js',
'!src/vs/css.build.js',
'!src/vs/loader.js', '!src/vs/loader.js',
'!src/vs/base/common/marked/marked.js', '!src/vs/base/common/marked/marked.js',
'!src/vs/base/common/winjs.base.js', '!src/vs/base/common/winjs.base.js',
@@ -78,12 +81,14 @@ const indentationFilter = [
'!src/vs/*/**/*.d.ts', '!src/vs/*/**/*.d.ts',
'!src/typings/**/*.d.ts', '!src/typings/**/*.d.ts',
'!extensions/**/*.d.ts', '!extensions/**/*.d.ts',
'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe}', '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns}',
'!build/{lib,tslintRules}/**/*.js', '!build/{lib,tslintRules}/**/*.js',
'!build/**/*.sh', '!build/**/*.sh',
'!build/tfs/**/*.js', '!build/azure-pipelines/**/*.js',
'!build/tfs/**/*.config', '!build/azure-pipelines/**/*.config',
'!**/Dockerfile', '!**/Dockerfile',
'!**/*.Dockerfile',
'!**/*.dockerfile',
'!extensions/markdown-language-features/media/*.js' '!extensions/markdown-language-features/media/*.js'
]; ];
@@ -96,6 +101,8 @@ const copyrightFilter = [
'!**/*.md', '!**/*.md',
'!**/*.bat', '!**/*.bat',
'!**/*.cmd', '!**/*.cmd',
'!**/*.ico',
'!**/*.icns',
'!**/*.xml', '!**/*.xml',
'!**/*.sh', '!**/*.sh',
'!**/*.txt', '!**/*.txt',

View File

@@ -13,7 +13,6 @@ const es = require('event-stream');
const util = require('./lib/util'); const util = require('./lib/util');
const remote = require('gulp-remote-src'); const remote = require('gulp-remote-src');
const zip = require('gulp-vinyl-zip'); const zip = require('gulp-vinyl-zip');
const assign = require('object-assign');
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const jeditor = require('gulp-json-editor'); const jeditor = require('gulp-json-editor');

View File

@@ -33,16 +33,17 @@ const i18n = require('./lib/i18n');
const serviceDownloader = require('service-downloader').ServiceDownloadProvider; const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
const platformInfo = require('service-downloader/out/platform').PlatformInformation; const platformInfo = require('service-downloader/out/platform').PlatformInformation;
const glob = require('glob'); const glob = require('glob');
// {{SQL CARBON EDIT}} - End
const deps = require('./dependencies'); const deps = require('./dependencies');
const getElectronVersion = require('./lib/electron').getElectronVersion; const getElectronVersion = require('./lib/electron').getElectronVersion;
const createAsar = require('./lib/asar').createAsar; const createAsar = require('./lib/asar').createAsar;
const minimist = require('minimist');
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname)); const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
// @ts-ignore // @ts-ignore
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
var del = require('del'); var del = require('del');
const extensionsRoot = path.join(root, 'extensions');
const extensionsProductionDependencies = deps.getProductionDependencies(extensionsRoot);
const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n)); const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n));
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const nodeModules = [ const nodeModules = [
@@ -56,28 +57,7 @@ const nodeModules = [
.concat(_.uniq(productionDependencies.map(d => d.name))) .concat(_.uniq(productionDependencies.map(d => d.name)))
.concat(baseModules); .concat(baseModules);
// Build // Build
const builtInExtensions = require('./builtInExtensions.json');
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
];
// {{SQL CARBON EDIT}}
const vsce = require('vsce');
const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
// the extension will be excluded from SQLOps package and will have separate vsix packages
'agent',
'import',
'profiler'
];
var azureExtensions = [ 'azurecore'];
const vscodeEntryPoints = _.flatten([ const vscodeEntryPoints = _.flatten([
buildfile.entrypoint('vs/workbench/workbench.main'), buildfile.entrypoint('vs/workbench/workbench.main'),
buildfile.base, buildfile.base,
@@ -90,14 +70,15 @@ const vscodeResources = [
'out-build/cli.js', 'out-build/cli.js',
'out-build/driver.js', 'out-build/driver.js',
'out-build/bootstrap.js', 'out-build/bootstrap.js',
'out-build/bootstrap-fork.js',
'out-build/bootstrap-amd.js', 'out-build/bootstrap-amd.js',
'out-build/bootstrap-window.js',
'out-build/paths.js', 'out-build/paths.js',
'out-build/vs/**/*.{svg,png,cur,html}', 'out-build/vs/**/*.{svg,png,cur,html}',
'out-build/vs/base/common/performance.js', 'out-build/vs/base/common/performance.js',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}',
'out-build/vs/base/browser/ui/octiconLabel/octicons/**', 'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
'out-build/vs/workbench/browser/media/*-theme.css', 'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/electron-browser/bootstrap/**',
'out-build/vs/workbench/parts/debug/**/*.json', 'out-build/vs/workbench/parts/debug/**/*.json',
'out-build/vs/workbench/parts/execution/**/*.scpt', 'out-build/vs/workbench/parts/execution/**/*.scpt',
'out-build/vs/workbench/parts/webview/electron-browser/webview-pre.js', 'out-build/vs/workbench/parts/webview/electron-browser/webview-pre.js',
@@ -106,6 +87,7 @@ const vscodeResources = [
'out-build/vs/workbench/parts/welcome/walkThrough/**/*.md', 'out-build/vs/workbench/parts/welcome/walkThrough/**/*.md',
'out-build/vs/workbench/services/files/**/*.exe', 'out-build/vs/workbench/services/files/**/*.exe',
'out-build/vs/workbench/services/files/**/*.md', 'out-build/vs/workbench/services/files/**/*.md',
'out-build/vs/code/electron-browser/workbench/**',
'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
'out-build/vs/code/electron-browser/issue/issueReporter.js', 'out-build/vs/code/electron-browser/issue/issueReporter.js',
'out-build/vs/code/electron-browser/processExplorer/processExplorer.js', 'out-build/vs/code/electron-browser/processExplorer/processExplorer.js',
@@ -153,21 +135,31 @@ gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compil
gulp.task('optimize-index-js', ['optimize-vscode'], () => { gulp.task('optimize-index-js', ['optimize-vscode'], () => {
const fullpath = path.join(process.cwd(), 'out-vscode/vs/workbench/electron-browser/bootstrap/index.js'); const fullpath = path.join(process.cwd(), 'out-vscode/vs/code/electron-browser/workbench/workbench.js');
const contents = fs.readFileSync(fullpath).toString(); const contents = fs.readFileSync(fullpath).toString();
const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules)); const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules));
fs.writeFileSync(fullpath, newContents); fs.writeFileSync(fullpath, newContents);
}); });
const baseUrl = `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`; const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
gulp.task('clean-minified-vscode', util.rimraf('out-vscode-min')); gulp.task('clean-minified-vscode', util.rimraf('out-vscode-min'));
gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-index-js'], common.minifyTask('out-vscode', baseUrl)); gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-index-js'], common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`));
// Package // Package
// @ts-ignore JSON checking: darwinCredits is optional // @ts-ignore JSON checking: darwinCredits is optional
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8')); const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
function darwinBundleDocumentType(extensions, icon) {
return {
name: product.nameLong + ' document',
role: 'Editor',
ostypes: ["TEXT", "utxt", "TUTX", "****"],
extensions: extensions,
iconFile: icon
};
}
const config = { const config = {
version: getElectronVersion(), version: getElectronVersion(),
productAppName: product.nameLong, productAppName: product.nameLong,
@@ -178,19 +170,16 @@ const config = {
darwinApplicationCategoryType: 'public.app-category.developer-tools', darwinApplicationCategoryType: 'public.app-category.developer-tools',
darwinHelpBookFolder: 'VS Code HelpBook', darwinHelpBookFolder: 'VS Code HelpBook',
darwinHelpBookName: 'VS Code HelpBook', darwinHelpBookName: 'VS Code HelpBook',
darwinBundleDocumentTypes: [{ darwinBundleDocumentTypes: [
name: product.nameLong + ' document', // {{SQL CARBON EDIT}} - Remove most document types and replace with ours
role: 'Editor', darwinBundleDocumentType(["csv", "json", "sqlplan", "sql", "xml"], 'resources/darwin/code_file.icns'),
ostypes: ["TEXT", "utxt", "TUTX", "****"], ],
// {{SQL CARBON EDIT}}
extensions: ["csv", "json", "sqlplan", "sql", "xml"],
iconFile: 'resources/darwin/code_file.icns'
}],
darwinBundleURLTypes: [{ darwinBundleURLTypes: [{
role: 'Viewer', role: 'Viewer',
name: product.nameLong, name: product.nameLong,
urlSchemes: [product.urlProtocol] urlSchemes: [product.urlProtocol]
}], }],
darwinForceDarkModeSupport: true,
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0, darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
linuxExecutableName: product.applicationName, linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico', winIcon: 'resources/win32/code.ico',
@@ -210,7 +199,7 @@ function getElectron(arch) {
}); });
return gulp.src('package.json') return gulp.src('package.json')
.pipe(json({ name: product.nameShort })) .pipe(json({ name: product.nameShort }))
.pipe(electron(electronOpts)) .pipe(electron(electronOpts))
.pipe(filter(['**', '!**/app/package.json'])) .pipe(filter(['**', '!**/app/package.json']))
.pipe(vfs.dest('.build/electron')); .pipe(vfs.dest('.build/electron'));
@@ -221,6 +210,8 @@ gulp.task('clean-electron', util.rimraf('.build/electron'));
gulp.task('electron', ['clean-electron'], getElectron(process.arch)); gulp.task('electron', ['clean-electron'], getElectron(process.arch));
gulp.task('electron-ia32', ['clean-electron'], getElectron('ia32')); gulp.task('electron-ia32', ['clean-electron'], getElectron('ia32'));
gulp.task('electron-x64', ['clean-electron'], getElectron('x64')); gulp.task('electron-x64', ['clean-electron'], getElectron('x64'));
gulp.task('electron-arm', ['clean-electron'], getElectron('arm'));
gulp.task('electron-arm64', ['clean-electron'], getElectron('arm64'));
/** /**
@@ -257,61 +248,6 @@ function computeChecksum(filename) {
return hash; return hash;
} }
function packageBuiltInExtensions() {
const sqlBuiltInLocalExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0);
sqlBuiltInLocalExtensionDescriptions.forEach(element => {
const packagePath = path.join(path.dirname(root), element.name + '.vsix');
console.info('Creating vsix for ' + element.path + ' result:' + packagePath);
vsce.createVSIX({
cwd: element.path,
packagePath: packagePath,
useYarn: true
});
});
}
// {{SQL CARBON EDIT}}
function packageAzureCoreTask(platform, arch) {
var destination = path.join(path.dirname(root), 'azuredatastudio') + (platform ? '-' + platform : '') + (arch ? '-' + arch : '');
if (platform === 'darwin') {
destination = path.join(destination, 'Azure Data Studio.app', 'Contents', 'Resources', 'app', 'extensions', 'azurecore');
} else {
destination = path.join(destination, 'resources', 'app', 'extensions', 'azurecore');
}
platform = platform || process.platform;
return () => {
const root = path.resolve(path.join(__dirname, '..'));
const localExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => azureExtensions.indexOf(name) > -1);
const localExtensions = es.merge(...localExtensionDescriptions.map(extension => {
return ext.fromLocal(extension.path);
}));
let result = localExtensions
.pipe(util.skipDirectories())
.pipe(util.fixWin32DirectoryPermissions())
.pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version']));
return result.pipe(vfs.dest(destination));
};
}
function packageTask(platform, arch, opts) { function packageTask(platform, arch, opts) {
opts = opts || {}; opts = opts || {};
@@ -325,48 +261,24 @@ function packageTask(platform, arch, opts) {
const checksums = computeChecksums(out, [ const checksums = computeChecksums(out, [
'vs/workbench/workbench.main.js', 'vs/workbench/workbench.main.js',
'vs/workbench/workbench.main.css', 'vs/workbench/workbench.main.css',
'vs/workbench/electron-browser/bootstrap/index.html', 'vs/code/electron-browser/workbench/workbench.html',
'vs/workbench/electron-browser/bootstrap/index.js', 'vs/code/electron-browser/workbench/workbench.js'
'vs/workbench/electron-browser/bootstrap/preload.js'
]); ]);
const src = gulp.src(out + '/**', { base: '.' }) const src = gulp.src(out + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); })); .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); }))
const root = path.resolve(path.join(__dirname, '..'));
const localExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
// {{SQL CARBON EDIT}}
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
packageBuiltInExtensions();
const localExtensions = es.merge(...localExtensionDescriptions.map(extension => {
return ext.fromLocal(extension.path)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
}));
// {{SQL CARBON EDIT}}
const extensionDepsSrc = [
..._.flatten(extensionsProductionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])),
];
const localExtensionDependencies = gulp.src(extensionDepsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
.pipe(util.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util.cleanNodeModule('typescript', ['**/**'], undefined));
const sources = es.merge(src, localExtensions, localExtensionDependencies)
.pipe(util.setExecutableBit(['**/*.sh'])) .pipe(util.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', '!**/*.js.map'])); .pipe(filter(['**', '!**/*.js.map']));
const root = path.resolve(path.join(__dirname, '..'));
// {{SQL CARBON EDIT}}
ext.packageBuiltInExtensions();
const sources = es.merge(src, ext.packageExtensionsStream({
sourceMappingURLBase: sourceMappingURLBase
}));
let version = packageJson.version; let version = packageJson.version;
// @ts-ignore JSON checking: quality is optional // @ts-ignore JSON checking: quality is optional
const quality = product.quality; const quality = product.quality;
@@ -377,8 +289,15 @@ function packageTask(platform, arch, opts) {
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const name = (platform === 'darwin') ? 'Azure Data Studio' : product.nameShort; const name = (platform === 'darwin') ? 'Azure Data Studio' : product.nameShort;
const packageJsonUpdates = { name, version };
// for linux url handling
if (platform === 'linux') {
packageJsonUpdates.desktopName = `${product.applicationName}-url-handler.desktop`;
}
const packageJsonStream = gulp.src(['package.json'], { base: '.' }) const packageJsonStream = gulp.src(['package.json'], { base: '.' })
.pipe(json({ name, version })); .pipe(json(packageJsonUpdates));
const date = new Date().toISOString(); const date = new Date().toISOString();
const productJsonUpdate = { commit, date, checksums }; const productJsonUpdate = { commit, date, checksums };
@@ -396,7 +315,7 @@ function packageTask(platform, arch, opts) {
// TODO the API should be copied to `out` during compile, not here // TODO the API should be copied to `out` during compile, not here
const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts')); const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts'));
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts')); const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts'));
const depsSrc = [ const depsSrc = [
@@ -408,16 +327,17 @@ function packageTask(platform, arch, opts) {
const deps = gulp.src(depsSrc, { base: '.', dot: true }) const deps = gulp.src(depsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json'])) .pipe(filter(['**', '!**/package-lock.json']))
.pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/*.js'])) .pipe(util.cleanNodeModule('vscode-sqlite3', ['binding.gyp', 'benchmark/**', 'cloudformation/**', 'deps/**', 'test/**', 'build/**', 'src/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/*.js']))
.pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('jschardet', ['dist/**'])) .pipe(util.cleanNodeModule('jschardet', ['dist/**']))
.pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js'])) .pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node'])) .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node']))
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
@@ -429,6 +349,7 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined)) .pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a'])) .pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a'])) .pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
// {{SQL CARBON EDIT}} - End
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node'])) .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar')); .pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
@@ -439,7 +360,7 @@ function packageTask(platform, arch, opts) {
'node_modules/slickgrid/**/*.*', 'node_modules/slickgrid/**/*.*',
'node_modules/underscore/**/*.*', 'node_modules/underscore/**/*.*',
'node_modules/zone.js/**/*.*', 'node_modules/zone.js/**/*.*',
'node_modules/chart.js/**/*.*' 'node_modules/chart.js/**/*.*',
], { base: '.', dot: true }); ], { base: '.', dot: true });
let all = es.merge( let all = es.merge(
@@ -456,7 +377,37 @@ function packageTask(platform, arch, opts) {
); );
if (platform === 'win32') { if (platform === 'win32') {
all = es.merge(all, gulp.src(['resources/win32/code_file.ico', 'resources/win32/code_70x70.png', 'resources/win32/code_150x150.png'], { base: '.' })); all = es.merge(all, gulp.src([
'resources/win32/bower.ico',
'resources/win32/c.ico',
'resources/win32/config.ico',
'resources/win32/cpp.ico',
'resources/win32/csharp.ico',
'resources/win32/css.ico',
'resources/win32/default.ico',
'resources/win32/go.ico',
'resources/win32/html.ico',
'resources/win32/jade.ico',
'resources/win32/java.ico',
'resources/win32/javascript.ico',
'resources/win32/json.ico',
'resources/win32/less.ico',
'resources/win32/markdown.ico',
'resources/win32/php.ico',
'resources/win32/powershell.ico',
'resources/win32/python.ico',
'resources/win32/react.ico',
'resources/win32/ruby.ico',
'resources/win32/sass.ico',
'resources/win32/shell.ico',
'resources/win32/sql.ico',
'resources/win32/typescript.ico',
'resources/win32/vue.ico',
'resources/win32/xml.ico',
'resources/win32/yaml.ico',
'resources/win32/code_70x70.png',
'resources/win32/code_150x150.png'
], { base: '.' }));
} else if (platform === 'linux') { } else if (platform === 'linux') {
all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' })); all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' }));
} else if (platform === 'darwin') { } else if (platform === 'darwin') {
@@ -481,6 +432,8 @@ function packageTask(platform, arch, opts) {
result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' }) result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
.pipe(replace('@@NAME@@', product.nameShort)) .pipe(replace('@@NAME@@', product.nameShort))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; }))); .pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' }) result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
@@ -491,6 +444,15 @@ function packageTask(platform, arch, opts) {
.pipe(rename('bin/' + product.applicationName))); .pipe(rename('bin/' + product.applicationName)));
} }
// submit all stats that have been collected
// during the build phase
if (opts.stats) {
result.on('end', () => {
const { submitAllStats } = require('./lib/stats');
submitAllStats(product, commit).then(() => console.log('Submitted bundle stats!'));
});
}
return result.pipe(vfs.dest(destination)); return result.pipe(vfs.dest(destination));
}; };
} }
@@ -498,9 +460,13 @@ function packageTask(platform, arch, opts) {
const buildRoot = path.dirname(root); const buildRoot = path.dirname(root);
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
gulp.task('vscode-win32-x64-azurecore', ['optimize-vscode'], packageAzureCoreTask('win32', 'x64')); gulp.task('vscode-win32-x64-azurecore', ['optimize-vscode'], ext.packageExtensionTask('azurecore', 'win32', 'x64'));
gulp.task('vscode-darwin-azurecore', ['optimize-vscode'], packageAzureCoreTask('darwin')); gulp.task('vscode-darwin-azurecore', ['optimize-vscode'], ext.packageExtensionTask('azurecore', 'darwin'));
gulp.task('vscode-linux-x64-azurecore', ['optimize-vscode'], packageAzureCoreTask('linux', 'x64')); gulp.task('vscode-linux-x64-azurecore', ['optimize-vscode'], ext.packageExtensionTask('azurecore', 'linux', 'x64'));
gulp.task('vscode-win32-x64-mssql', ['vscode-linux-x64-azurecore', 'optimize-vscode'], ext.packageExtensionTask('mssql', 'win32', 'x64'));
gulp.task('vscode-darwin-mssql', ['vscode-linux-x64-azurecore', 'optimize-vscode'], ext.packageExtensionTask('mssql', 'darwin'));
gulp.task('vscode-linux-x64-mssql', ['vscode-linux-x64-azurecore', 'optimize-vscode'], ext.packageExtensionTask('mssql', 'linux', 'x64'));
gulp.task('clean-vscode-win32-ia32', util.rimraf(path.join(buildRoot, 'azuredatastudio-win32-ia32'))); gulp.task('clean-vscode-win32-ia32', util.rimraf(path.join(buildRoot, 'azuredatastudio-win32-ia32')));
gulp.task('clean-vscode-win32-x64', util.rimraf(path.join(buildRoot, 'azuredatastudio-win32-x64'))); gulp.task('clean-vscode-win32-x64', util.rimraf(path.join(buildRoot, 'azuredatastudio-win32-x64')));
@@ -508,20 +474,23 @@ gulp.task('clean-vscode-darwin', util.rimraf(path.join(buildRoot, 'azuredatastud
gulp.task('clean-vscode-linux-ia32', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-ia32'))); gulp.task('clean-vscode-linux-ia32', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-ia32')));
gulp.task('clean-vscode-linux-x64', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-x64'))); gulp.task('clean-vscode-linux-x64', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-x64')));
gulp.task('clean-vscode-linux-arm', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-arm'))); gulp.task('clean-vscode-linux-arm', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-arm')));
gulp.task('clean-vscode-linux-arm64', util.rimraf(path.join(buildRoot, 'azuredatastudio-linux-arm64')));
gulp.task('vscode-win32-ia32', ['optimize-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32')); gulp.task('vscode-win32-ia32', ['optimize-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32'));
gulp.task('vscode-win32-x64', ['vscode-win32-x64-azurecore', 'optimize-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64')); gulp.task('vscode-win32-x64', ['vscode-win32-x64-azurecore', 'vscode-win32-x64-mssql', 'optimize-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64'));
gulp.task('vscode-darwin', ['vscode-darwin-azurecore', 'optimize-vscode', 'clean-vscode-darwin'], packageTask('darwin')); gulp.task('vscode-darwin', ['vscode-darwin-azurecore', 'vscode-darwin-mssql', 'optimize-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { stats: true }));
gulp.task('vscode-linux-ia32', ['optimize-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32')); gulp.task('vscode-linux-ia32', ['optimize-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32'));
gulp.task('vscode-linux-x64', ['vscode-linux-x64-azurecore', 'optimize-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64')); gulp.task('vscode-linux-x64', ['vscode-linux-x64-azurecore', 'vscode-linux-x64-mssql', 'optimize-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64'));
gulp.task('vscode-linux-arm', ['optimize-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm')); gulp.task('vscode-linux-arm', ['optimize-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm'));
gulp.task('vscode-linux-arm64', ['optimize-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64'));
gulp.task('vscode-win32-ia32-min', ['minify-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32', { minified: true })); gulp.task('vscode-win32-ia32-min', ['minify-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32', { minified: true }));
gulp.task('vscode-win32-x64-min', ['minify-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64', { minified: true })); gulp.task('vscode-win32-x64-min', ['minify-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64', { minified: true }));
gulp.task('vscode-darwin-min', ['minify-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { minified: true })); gulp.task('vscode-darwin-min', ['minify-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { minified: true, stats: true }));
gulp.task('vscode-linux-ia32-min', ['minify-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32', { minified: true })); gulp.task('vscode-linux-ia32-min', ['minify-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32', { minified: true }));
gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64', { minified: true })); gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64', { minified: true }));
gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true })); gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true }));
gulp.task('vscode-linux-arm64-min', ['minify-vscode', 'clean-vscode-linux-arm64'], packageTask('linux', 'arm64', { minified: true }));
// Transifex Localizations // Transifex Localizations
@@ -557,7 +526,7 @@ gulp.task('vscode-translations-push', ['optimize-vscode'], function () {
).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken)); ).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken));
}); });
gulp.task('vscode-translations-push-test', ['optimize-vscode'], function () { gulp.task('vscode-translations-export', ['optimize-vscode'], function () {
const pathToMetadata = './out-vscode/nls.metadata.json'; const pathToMetadata = './out-vscode/nls.metadata.json';
const pathToExtensions = './extensions/*'; const pathToExtensions = './extensions/*';
const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';
@@ -566,46 +535,44 @@ gulp.task('vscode-translations-push-test', ['optimize-vscode'], function () {
gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
// {{SQL CARBON EDIT}} ).pipe(vfs.dest('../vscode-translations-export'));
// disable since function makes calls to VS Code Transifex API
// ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
).pipe(vfs.dest('../vscode-transifex-input'));
}); });
gulp.task('vscode-translations-pull', function () { gulp.task('vscode-translations-pull', function () {
[...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => { return es.merge([...i18n.defaultLanguages, ...i18n.extraLanguages].map(language => {
i18n.pullCoreAndExtensionsXlfFiles(apiHostname, apiName, apiToken, language).pipe(vfs.dest(`../vscode-localization/${language.id}/build`));
let includeDefault = !!innoSetupConfig[language.id].defaultInfo; let includeDefault = !!innoSetupConfig[language.id].defaultInfo;
i18n.pullSetupXlfFiles(apiHostname, apiName, apiToken, language, includeDefault).pipe(vfs.dest(`../vscode-localization/${language.id}/setup`)); return i18n.pullSetupXlfFiles(apiHostname, apiName, apiToken, language, includeDefault).pipe(vfs.dest(`../vscode-translations-import/${language.id}/setup`));
}); }));
}); });
gulp.task('vscode-translations-import', function () { gulp.task('vscode-translations-import', function () {
// {{SQL CARBON EDIT}} - Replace function body with our own
[...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => { [...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => {
gulp.src(`../vscode-localization/${language.id}/build/*/*.xlf`) gulp.src(`../vscode-localization/${language.id}/build/*/*.xlf`)
.pipe(i18n.prepareI18nFiles()) .pipe(i18n.prepareI18nFiles())
.pipe(vfs.dest(`./i18n/${language.folderName}`)); .pipe(vfs.dest(`./i18n/${language.folderName}`));
// {{SQL CARBON EDIT}}
// gulp.src(`../vscode-localization/${language.id}/setup/*/*.xlf`)
// .pipe(i18n.prepareIslFiles(language, innoSetupConfig[language.id]))
// .pipe(vfs.dest(`./build/win32/i18n`));
}); });
// {{SQL CARBON EDIT}} - End
}); });
// Sourcemaps // Sourcemaps
gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => { gulp.task('upload-vscode-sourcemaps', ['vscode-darwin-min', 'minify-vscode'], () => {
const vs = gulp.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' }) const vs = gulp.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' })
.pipe(es.mapSync(f => { .pipe(es.mapSync(f => {
f.path = `${f.base}/core/${f.relative}`; f.path = `${f.base}/core/${f.relative}`;
return f; return f;
})); }));
const extensions = gulp.src('extensions/**/out/**/*.map', { base: '.' }); const extensionsOut = gulp.src('extensions/**/out/**/*.map', { base: '.' });
const extensionsDist = gulp.src('extensions/**/dist/**/*.map', { base: '.' });
return es.merge(vs, extensions) return es.merge(vs, extensionsOut, extensionsDist)
.pipe(es.through(function (data) {
// debug
console.log('Uploading Sourcemap', data.relative);
this.emit('data', data);
}))
.pipe(azure.upload({ .pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT, account: process.env.AZURE_STORAGE_ACCOUNT,
key: process.env.AZURE_STORAGE_ACCESS_KEY, key: process.env.AZURE_STORAGE_ACCESS_KEY,
@@ -650,7 +617,7 @@ function getSettingsSearchBuildId(packageJson) {
const branch = process.env.BUILD_SOURCEBRANCH; const branch = process.env.BUILD_SOURCEBRANCH;
const branchId = branch.indexOf('/release/') >= 0 ? 0 : const branchId = branch.indexOf('/release/') >= 0 ? 0 :
/\/master$/.test(branch) ? 1 : /\/master$/.test(branch) ? 1 :
2; // Some unexpected branch 2; // Some unexpected branch
const out = cp.execSync(`git rev-list HEAD --count`); const out = cp.execSync(`git rev-list HEAD --count`);
const count = parseInt(out.toString()); const count = parseInt(out.toString());
@@ -723,6 +690,5 @@ function installService() {
} }
gulp.task('install-sqltoolsservice', () => { gulp.task('install-sqltoolsservice', () => {
return installService(); return installService();
}); });

View File

@@ -19,7 +19,7 @@ const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000); const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
function getDebPackageArch(arch) { function getDebPackageArch(arch) {
return { x64: 'amd64', ia32: 'i386', arm: 'armhf' }[arch]; return { x64: 'amd64', ia32: 'i386', arm: 'armhf', arm64: "arm64" }[arch];
} }
function prepareDebPackage(arch) { function prepareDebPackage(arch) {
@@ -30,11 +30,17 @@ function prepareDebPackage(arch) {
return function () { return function () {
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' }) const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
.pipe(rename('usr/share/applications/' + product.applicationName + '.desktop'));
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
.pipe(rename('usr/share/applications/' + product.applicationName + '-url-handler.desktop'));
const desktops = es.merge(desktop, desktopUrlHandler)
.pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort)) .pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@ICON@@', product.applicationName)) .pipe(replace('@@ICON@@', product.applicationName))
.pipe(rename('usr/share/applications/' + product.applicationName + '.desktop')); .pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' }) const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_LONG@@', product.nameLong))
@@ -79,7 +85,7 @@ function prepareDebPackage(arch) {
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) .pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@'))
.pipe(rename('DEBIAN/postinst')); .pipe(rename('DEBIAN/postinst'));
const all = es.merge(control, postinst, postrm, prerm, desktop, appdata, icon, code); const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, icon, code);
return all.pipe(vfs.dest(destination)); return all.pipe(vfs.dest(destination));
}; };
@@ -99,7 +105,7 @@ function getRpmBuildPath(rpmArch) {
} }
function getRpmPackageArch(arch) { function getRpmPackageArch(arch) {
return { x64: 'x86_64', ia32: 'i386', arm: 'armhf' }[arch]; return { x64: 'x86_64', ia32: 'i386', arm: 'armhf', arm64: "arm64" }[arch];
} }
function prepareRpmPackage(arch) { function prepareRpmPackage(arch) {
@@ -109,11 +115,17 @@ function prepareRpmPackage(arch) {
return function () { return function () {
const desktop = gulp.src('resources/linux/code.desktop', { base: '.' }) const desktop = gulp.src('resources/linux/code.desktop', { base: '.' })
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '.desktop'));
const desktopUrlHandler = gulp.src('resources/linux/code-url-handler.desktop', { base: '.' })
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '-url-handler.desktop'));
const desktops = es.merge(desktop, desktopUrlHandler)
.pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_LONG@@', product.nameLong))
.pipe(replace('@@NAME_SHORT@@', product.nameShort)) .pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@ICON@@', product.applicationName)) .pipe(replace('@@ICON@@', product.applicationName))
.pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '.desktop')); .pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' }) const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
.pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@NAME_LONG@@', product.nameLong))
@@ -144,7 +156,7 @@ function prepareRpmPackage(arch) {
const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' }) const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' })
.pipe(rename('SOURCES/' + product.applicationName + '.xpm')); .pipe(rename('SOURCES/' + product.applicationName + '.xpm'));
const all = es.merge(code, desktop, appdata, icon, spec, specIcon); const all = es.merge(code, desktops, appdata, icon, spec, specIcon);
return all.pipe(vfs.dest(getRpmBuildPath(rpmArch))); return all.pipe(vfs.dest(getRpmBuildPath(rpmArch)));
}; };
@@ -162,6 +174,7 @@ function buildRpmPackage(arch) {
'cp "' + rpmOut + '/$(ls ' + rpmOut + ')" ' + destination + '/' 'cp "' + rpmOut + '/$(ls ' + rpmOut + ')" ' + destination + '/'
]); ]);
} }
function getSnapBuildPath(arch) { function getSnapBuildPath(arch) {
return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`; return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`;
} }
@@ -182,17 +195,21 @@ function prepareSnapPackage(arch) {
.pipe(rename(`usr/share/pixmaps/${product.applicationName}.png`)); .pipe(rename(`usr/share/pixmaps/${product.applicationName}.png`));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir }) const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; })); .pipe(rename(function (p) { p.dirname = `usr/share/${product.applicationName}/${p.dirname}`; }));
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' }) const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', packageJson.version)) .pipe(replace('@@VERSION@@', `${packageJson.version}-${linuxPackageRevision}`))
.pipe(rename('snap/snapcraft.yaml')); .pipe(rename('snap/snapcraft.yaml'));
const snapUpdate = gulp.src('resources/linux/snap/snapUpdate.sh', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename(`usr/share/${product.applicationName}/snapUpdate.sh`));
const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' }) const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' })
.pipe(rename('electron-launch')); .pipe(rename('electron-launch'));
const all = es.merge(desktop, icon, code, snapcraft, electronLaunch); const all = es.merge(desktop, icon, code, snapcraft, electronLaunch, snapUpdate);
return all.pipe(vfs.dest(destination)); return all.pipe(vfs.dest(destination));
}; };
@@ -200,11 +217,7 @@ function prepareSnapPackage(arch) {
function buildSnapPackage(arch) { function buildSnapPackage(arch) {
const snapBuildPath = getSnapBuildPath(arch); const snapBuildPath = getSnapBuildPath(arch);
const snapFilename = `${product.applicationName}-${packageJson.version}-${linuxPackageRevision}-${arch}.snap`; return shell.task(`cd ${snapBuildPath} && snapcraft build`);
return shell.task([
`chmod +x ${snapBuildPath}/electron-launch`,
`cd ${snapBuildPath} && snapcraft snap --output ../${snapFilename}`
]);
} }
function getFlatpakArch(arch) { function getFlatpakArch(arch) {
@@ -284,33 +297,39 @@ function buildFlatpak(arch) {
gulp.task('clean-vscode-linux-ia32-deb', util.rimraf('.build/linux/deb/i386')); gulp.task('clean-vscode-linux-ia32-deb', util.rimraf('.build/linux/deb/i386'));
gulp.task('clean-vscode-linux-x64-deb', util.rimraf('.build/linux/deb/amd64')); gulp.task('clean-vscode-linux-x64-deb', util.rimraf('.build/linux/deb/amd64'));
gulp.task('clean-vscode-linux-arm-deb', util.rimraf('.build/linux/deb/armhf')); gulp.task('clean-vscode-linux-arm-deb', util.rimraf('.build/linux/deb/armhf'));
gulp.task('clean-vscode-linux-arm64-deb', util.rimraf('.build/linux/deb/arm64'));
gulp.task('clean-vscode-linux-ia32-rpm', util.rimraf('.build/linux/rpm/i386')); gulp.task('clean-vscode-linux-ia32-rpm', util.rimraf('.build/linux/rpm/i386'));
gulp.task('clean-vscode-linux-x64-rpm', util.rimraf('.build/linux/rpm/x86_64')); gulp.task('clean-vscode-linux-x64-rpm', util.rimraf('.build/linux/rpm/x86_64'));
gulp.task('clean-vscode-linux-arm-rpm', util.rimraf('.build/linux/rpm/armhf')); gulp.task('clean-vscode-linux-arm-rpm', util.rimraf('.build/linux/rpm/armhf'));
gulp.task('clean-vscode-linux-arm64-rpm', util.rimraf('.build/linux/rpm/arm64'));
gulp.task('clean-vscode-linux-ia32-snap', util.rimraf('.build/linux/snap/x64')); gulp.task('clean-vscode-linux-ia32-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-x64-snap', util.rimraf('.build/linux/snap/x64')); gulp.task('clean-vscode-linux-x64-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-arm-snap', util.rimraf('.build/linux/snap/x64')); gulp.task('clean-vscode-linux-arm-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-ia32-flatpak', util.rimraf('.build/linux/flatpak/i386')); gulp.task('clean-vscode-linux-arm64-snap', util.rimraf('.build/linux/snap/x64'));
gulp.task('clean-vscode-linux-x64-flatpak', util.rimraf('.build/linux/flatpak/x86_64'));
gulp.task('clean-vscode-linux-arm-flatpak', util.rimraf('.build/linux/flatpak/arm'));
gulp.task('vscode-linux-ia32-prepare-deb', ['clean-vscode-linux-ia32-deb'], prepareDebPackage('ia32')); gulp.task('vscode-linux-ia32-prepare-deb', ['clean-vscode-linux-ia32-deb'], prepareDebPackage('ia32'));
gulp.task('vscode-linux-x64-prepare-deb', ['clean-vscode-linux-x64-deb'], prepareDebPackage('x64')); gulp.task('vscode-linux-x64-prepare-deb', ['clean-vscode-linux-x64-deb'], prepareDebPackage('x64'));
gulp.task('vscode-linux-arm-prepare-deb', ['clean-vscode-linux-arm-deb'], prepareDebPackage('arm')); gulp.task('vscode-linux-arm-prepare-deb', ['clean-vscode-linux-arm-deb'], prepareDebPackage('arm'));
gulp.task('vscode-linux-arm64-prepare-deb', ['clean-vscode-linux-arm64-deb'], prepareDebPackage('arm64'));
gulp.task('vscode-linux-ia32-build-deb', ['vscode-linux-ia32-prepare-deb'], buildDebPackage('ia32')); gulp.task('vscode-linux-ia32-build-deb', ['vscode-linux-ia32-prepare-deb'], buildDebPackage('ia32'));
gulp.task('vscode-linux-x64-build-deb', ['vscode-linux-x64-prepare-deb'], buildDebPackage('x64')); gulp.task('vscode-linux-x64-build-deb', ['vscode-linux-x64-prepare-deb'], buildDebPackage('x64'));
gulp.task('vscode-linux-arm-build-deb', ['vscode-linux-arm-prepare-deb'], buildDebPackage('arm')); gulp.task('vscode-linux-arm-build-deb', ['vscode-linux-arm-prepare-deb'], buildDebPackage('arm'));
gulp.task('vscode-linux-arm64-build-deb', ['vscode-linux-arm64-prepare-deb'], buildDebPackage('arm64'));
gulp.task('vscode-linux-ia32-prepare-rpm', ['clean-vscode-linux-ia32-rpm'], prepareRpmPackage('ia32')); gulp.task('vscode-linux-ia32-prepare-rpm', ['clean-vscode-linux-ia32-rpm'], prepareRpmPackage('ia32'));
gulp.task('vscode-linux-x64-prepare-rpm', ['clean-vscode-linux-x64-rpm'], prepareRpmPackage('x64')); gulp.task('vscode-linux-x64-prepare-rpm', ['clean-vscode-linux-x64-rpm'], prepareRpmPackage('x64'));
gulp.task('vscode-linux-arm-prepare-rpm', ['clean-vscode-linux-arm-rpm'], prepareRpmPackage('arm')); gulp.task('vscode-linux-arm-prepare-rpm', ['clean-vscode-linux-arm-rpm'], prepareRpmPackage('arm'));
gulp.task('vscode-linux-arm64-prepare-rpm', ['clean-vscode-linux-arm64-rpm'], prepareRpmPackage('arm64'));
gulp.task('vscode-linux-ia32-build-rpm', ['vscode-linux-ia32-prepare-rpm'], buildRpmPackage('ia32')); gulp.task('vscode-linux-ia32-build-rpm', ['vscode-linux-ia32-prepare-rpm'], buildRpmPackage('ia32'));
gulp.task('vscode-linux-x64-build-rpm', ['vscode-linux-x64-prepare-rpm'], buildRpmPackage('x64')); gulp.task('vscode-linux-x64-build-rpm', ['vscode-linux-x64-prepare-rpm'], buildRpmPackage('x64'));
gulp.task('vscode-linux-arm-build-rpm', ['vscode-linux-arm-prepare-rpm'], buildRpmPackage('arm')); gulp.task('vscode-linux-arm-build-rpm', ['vscode-linux-arm-prepare-rpm'], buildRpmPackage('arm'));
gulp.task('vscode-linux-arm64-build-rpm', ['vscode-linux-arm64-prepare-rpm'], buildRpmPackage('arm64'));
gulp.task('vscode-linux-ia32-prepare-snap', ['clean-vscode-linux-ia32-snap'], prepareSnapPackage('ia32')); gulp.task('vscode-linux-ia32-prepare-snap', ['clean-vscode-linux-ia32-snap'], prepareSnapPackage('ia32'));
gulp.task('vscode-linux-x64-prepare-snap', ['clean-vscode-linux-x64-snap'], prepareSnapPackage('x64')); gulp.task('vscode-linux-x64-prepare-snap', ['clean-vscode-linux-x64-snap'], prepareSnapPackage('x64'));
gulp.task('vscode-linux-arm-prepare-snap', ['clean-vscode-linux-arm-snap'], prepareSnapPackage('arm')); gulp.task('vscode-linux-arm-prepare-snap', ['clean-vscode-linux-arm-snap'], prepareSnapPackage('arm'));
gulp.task('vscode-linux-arm64-prepare-snap', ['clean-vscode-linux-arm64-snap'], prepareSnapPackage('arm64'));
gulp.task('vscode-linux-ia32-build-snap', ['vscode-linux-ia32-prepare-snap'], buildSnapPackage('ia32')); gulp.task('vscode-linux-ia32-build-snap', ['vscode-linux-ia32-prepare-snap'], buildSnapPackage('ia32'));
gulp.task('vscode-linux-x64-build-snap', ['vscode-linux-x64-prepare-snap'], buildSnapPackage('x64')); gulp.task('vscode-linux-x64-build-snap', ['vscode-linux-x64-prepare-snap'], buildSnapPackage('x64'));
gulp.task('vscode-linux-arm-build-snap', ['vscode-linux-arm-prepare-snap'], buildSnapPackage('arm')); gulp.task('vscode-linux-arm-build-snap', ['vscode-linux-arm-prepare-snap'], buildSnapPackage('arm'));
gulp.task('vscode-linux-arm64-build-snap', ['vscode-linux-arm64-prepare-snap'], buildSnapPackage('arm64'));

View File

@@ -15,6 +15,7 @@ const util = require('./lib/util');
const pkg = require('../package.json'); const pkg = require('../package.json');
const product = require('../product.json'); const product = require('../product.json');
const vfs = require('vinyl-fs'); const vfs = require('vinyl-fs');
const rcedit = require('rcedit');
const mkdirp = require('mkdirp'); const mkdirp = require('mkdirp');
const repoPath = path.dirname(__dirname); const repoPath = path.dirname(__dirname);
@@ -25,18 +26,21 @@ const zipPath = arch => path.join(zipDir(arch), `VSCode-win32-${arch}.zip`);
const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`); const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
const issPath = path.join(__dirname, 'win32', 'code.iss'); const issPath = path.join(__dirname, 'win32', 'code.iss');
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe'); const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
const signPS1 = path.join(repoPath, 'build', 'tfs', 'win32', 'sign.ps1'); const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
function packageInnoSetup(iss, options, cb) { function packageInnoSetup(iss, options, cb) {
options = options || {}; options = options || {};
const definitions = options.definitions || {}; const definitions = options.definitions || {};
const debug = process.argv.some(arg => arg === '--debug-inno');
if (debug) { if (process.argv.some(arg => arg === '--debug-inno')) {
definitions['Debug'] = 'true'; definitions['Debug'] = 'true';
} }
if (process.argv.some(arg => arg === '--sign')) {
definitions['Sign'] = 'true';
}
const keys = Object.keys(definitions); const keys = Object.keys(definitions);
keys.forEach(key => assert(typeof definitions[key] === 'string', `Missing value for '${key}' in Inno Setup package step`)); keys.forEach(key => assert(typeof definitions[key] === 'string', `Missing value for '${key}' in Inno Setup package step`));
@@ -136,4 +140,14 @@ function copyInnoUpdater(arch) {
} }
gulp.task('vscode-win32-ia32-copy-inno-updater', copyInnoUpdater('ia32')); gulp.task('vscode-win32-ia32-copy-inno-updater', copyInnoUpdater('ia32'));
gulp.task('vscode-win32-x64-copy-inno-updater', copyInnoUpdater('x64')); gulp.task('vscode-win32-x64-copy-inno-updater', copyInnoUpdater('x64'));
function patchInnoUpdater(arch) {
return cb => {
const icon = path.join(repoPath, 'resources', 'win32', 'code.ico');
rcedit(path.join(buildPath(arch), 'tools', 'inno_updater.exe'), { icon }, cb);
};
}
gulp.task('vscode-win32-ia32-inno-updater', ['vscode-win32-ia32-copy-inno-updater'], patchInnoUpdater('ia32'));
gulp.task('vscode-win32-x64-inno-updater', ['vscode-win32-x64-copy-inno-updater'], patchInnoUpdater('x64'));

15
build/jsconfig.json Normal file
View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"jsx": "preserve",
"checkJs": true
},
"include": [
"**/*.js"
],
"exclude": [
"node_modules",
"**/node_modules/*"
]
}

View File

@@ -4,33 +4,33 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var path = require("path"); const path = require("path");
var es = require("event-stream"); const es = require("event-stream");
var pickle = require("chromium-pickle-js"); const pickle = require('chromium-pickle-js');
var Filesystem = require("asar/lib/filesystem"); const Filesystem = require('asar/lib/filesystem');
var VinylFile = require("vinyl"); const VinylFile = require("vinyl");
var minimatch = require("minimatch"); const minimatch = require("minimatch");
function createAsar(folderPath, unpackGlobs, destFilename) { function createAsar(folderPath, unpackGlobs, destFilename) {
var shouldUnpackFile = function (file) { const shouldUnpackFile = (file) => {
for (var i = 0; i < unpackGlobs.length; i++) { for (let i = 0; i < unpackGlobs.length; i++) {
if (minimatch(file.relative, unpackGlobs[i])) { if (minimatch(file.relative, unpackGlobs[i])) {
return true; return true;
} }
} }
return false; return false;
}; };
var filesystem = new Filesystem(folderPath); const filesystem = new Filesystem(folderPath);
var out = []; const out = [];
// Keep track of pending inserts // Keep track of pending inserts
var pendingInserts = 0; let pendingInserts = 0;
var onFileInserted = function () { pendingInserts--; }; let onFileInserted = () => { pendingInserts--; };
// Do not insert twice the same directory // Do not insert twice the same directory
var seenDir = {}; const seenDir = {};
var insertDirectoryRecursive = function (dir) { const insertDirectoryRecursive = (dir) => {
if (seenDir[dir]) { if (seenDir[dir]) {
return; return;
} }
var lastSlash = dir.lastIndexOf('/'); let lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) { if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\'); lastSlash = dir.lastIndexOf('\\');
} }
@@ -40,8 +40,8 @@ function createAsar(folderPath, unpackGlobs, destFilename) {
seenDir[dir] = true; seenDir[dir] = true;
filesystem.insertDirectory(dir); filesystem.insertDirectory(dir);
}; };
var insertDirectoryForFile = function (file) { const insertDirectoryForFile = (file) => {
var lastSlash = file.lastIndexOf('/'); let lastSlash = file.lastIndexOf('/');
if (lastSlash === -1) { if (lastSlash === -1) {
lastSlash = file.lastIndexOf('\\'); lastSlash = file.lastIndexOf('\\');
} }
@@ -49,7 +49,7 @@ function createAsar(folderPath, unpackGlobs, destFilename) {
insertDirectoryRecursive(file.substring(0, lastSlash)); insertDirectoryRecursive(file.substring(0, lastSlash));
} }
}; };
var insertFile = function (relativePath, stat, shouldUnpack) { const insertFile = (relativePath, stat, shouldUnpack) => {
insertDirectoryForFile(relativePath); insertDirectoryForFile(relativePath);
pendingInserts++; pendingInserts++;
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted); filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
@@ -59,13 +59,13 @@ function createAsar(folderPath, unpackGlobs, destFilename) {
return; return;
} }
if (!file.stat.isFile()) { if (!file.stat.isFile()) {
throw new Error("unknown item in stream!"); throw new Error(`unknown item in stream!`);
} }
var shouldUnpack = shouldUnpackFile(file); const shouldUnpack = shouldUnpackFile(file);
insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack); insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
if (shouldUnpack) { if (shouldUnpack) {
// The file goes outside of xx.asar, in a folder xx.asar.unpacked // The file goes outside of xx.asar, in a folder xx.asar.unpacked
var relative = path.relative(folderPath, file.path); const relative = path.relative(folderPath, file.path);
this.queue(new VinylFile({ this.queue(new VinylFile({
cwd: folderPath, cwd: folderPath,
base: folderPath, base: folderPath,
@@ -79,34 +79,33 @@ function createAsar(folderPath, unpackGlobs, destFilename) {
out.push(file.contents); out.push(file.contents);
} }
}, function () { }, function () {
var _this = this; let finish = () => {
var finish = function () {
{ {
var headerPickle = pickle.createEmpty(); const headerPickle = pickle.createEmpty();
headerPickle.writeString(JSON.stringify(filesystem.header)); headerPickle.writeString(JSON.stringify(filesystem.header));
var headerBuf = headerPickle.toBuffer(); const headerBuf = headerPickle.toBuffer();
var sizePickle = pickle.createEmpty(); const sizePickle = pickle.createEmpty();
sizePickle.writeUInt32(headerBuf.length); sizePickle.writeUInt32(headerBuf.length);
var sizeBuf = sizePickle.toBuffer(); const sizeBuf = sizePickle.toBuffer();
out.unshift(headerBuf); out.unshift(headerBuf);
out.unshift(sizeBuf); out.unshift(sizeBuf);
} }
var contents = Buffer.concat(out); const contents = Buffer.concat(out);
out.length = 0; out.length = 0;
_this.queue(new VinylFile({ this.queue(new VinylFile({
cwd: folderPath, cwd: folderPath,
base: folderPath, base: folderPath,
path: destFilename, path: destFilename,
contents: contents contents: contents
})); }));
_this.queue(null); this.queue(null);
}; };
// Call finish() only when all file inserts have finished... // Call finish() only when all file inserts have finished...
if (pendingInserts === 0) { if (pendingInserts === 0) {
finish(); finish();
} }
else { else {
onFileInserted = function () { onFileInserted = () => {
pendingInserts--; pendingInserts--;
if (pendingInserts === 0) { if (pendingInserts === 0) {
finish(); finish();

View File

@@ -7,8 +7,8 @@
import * as path from 'path'; import * as path from 'path';
import * as es from 'event-stream'; import * as es from 'event-stream';
import * as pickle from 'chromium-pickle-js'; const pickle = require('chromium-pickle-js');
import * as Filesystem from 'asar/lib/filesystem'; const Filesystem = require('asar/lib/filesystem');
import * as VinylFile from 'vinyl'; import * as VinylFile from 'vinyl';
import * as minimatch from 'minimatch'; import * as minimatch from 'minimatch';

View File

@@ -49,7 +49,7 @@ function syncMarketplaceExtension(extension) {
rimraf.sync(getExtensionPath(extension)); rimraf.sync(getExtensionPath(extension));
return ext.fromMarketplace(extension.name, extension.version) return ext.fromMarketplace(extension.name, extension.version, extension.metadata)
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`)) .pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`))
.pipe(vfs.dest('.build/builtInExtensions')) .pipe(vfs.dest('.build/builtInExtensions'))
.on('end', () => util.log(util.colors.blue('[marketplace]'), extension.name, util.colors.green('✔︎'))); .on('end', () => util.log(util.colors.blue('[marketplace]'), extension.name, util.colors.green('✔︎')));

View File

@@ -4,19 +4,19 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var vm = require("vm"); const vm = require("vm");
/** /**
* Bundle `entryPoints` given config `config`. * Bundle `entryPoints` given config `config`.
*/ */
function bundle(entryPoints, config, callback) { function bundle(entryPoints, config, callback) {
var entryPointsMap = {}; const entryPointsMap = {};
entryPoints.forEach(function (module) { entryPoints.forEach((module) => {
entryPointsMap[module.name] = module; entryPointsMap[module.name] = module;
}); });
var allMentionedModulesMap = {}; const allMentionedModulesMap = {};
entryPoints.forEach(function (module) { entryPoints.forEach((module) => {
allMentionedModulesMap[module.name] = true; allMentionedModulesMap[module.name] = true;
(module.include || []).forEach(function (includedModule) { (module.include || []).forEach(function (includedModule) {
allMentionedModulesMap[includedModule] = true; allMentionedModulesMap[includedModule] = true;
@@ -25,26 +25,30 @@ function bundle(entryPoints, config, callback) {
allMentionedModulesMap[excludedModule] = true; allMentionedModulesMap[excludedModule] = true;
}); });
}); });
var code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js')); const code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js'));
var r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});'); const r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});');
var loaderModule = { exports: {} }; const loaderModule = { exports: {} };
r.call({}, require, loaderModule, loaderModule.exports); r.call({}, require, loaderModule, loaderModule.exports);
var loader = loaderModule.exports; const loader = loaderModule.exports;
config.isBuild = true; config.isBuild = true;
config.paths = config.paths || {}; config.paths = config.paths || {};
config.paths['vs/nls'] = 'out-build/vs/nls.build'; if (!config.paths['vs/nls']) {
config.paths['vs/css'] = 'out-build/vs/css.build'; config.paths['vs/nls'] = 'out-build/vs/nls.build';
}
if (!config.paths['vs/css']) {
config.paths['vs/css'] = 'out-build/vs/css.build';
}
loader.config(config); loader.config(config);
loader(['require'], function (localRequire) { loader(['require'], (localRequire) => {
var resolvePath = function (path) { const resolvePath = (path) => {
var r = localRequire.toUrl(path); const r = localRequire.toUrl(path);
if (!/\.js/.test(r)) { if (!/\.js/.test(r)) {
return r + '.js'; return r + '.js';
} }
return r; return r;
}; };
for (var moduleId in entryPointsMap) { for (const moduleId in entryPointsMap) {
var entryPoint = entryPointsMap[moduleId]; const entryPoint = entryPointsMap[moduleId];
if (entryPoint.append) { if (entryPoint.append) {
entryPoint.append = entryPoint.append.map(resolvePath); entryPoint.append = entryPoint.append.map(resolvePath);
} }
@@ -53,59 +57,59 @@ function bundle(entryPoints, config, callback) {
} }
} }
}); });
loader(Object.keys(allMentionedModulesMap), function () { loader(Object.keys(allMentionedModulesMap), () => {
var modules = loader.getBuildInfo(); const modules = loader.getBuildInfo();
var partialResult = emitEntryPoints(modules, entryPointsMap); const partialResult = emitEntryPoints(modules, entryPointsMap);
var cssInlinedResources = loader('vs/css').getInlinedResources(); const cssInlinedResources = loader('vs/css').getInlinedResources();
callback(null, { callback(null, {
files: partialResult.files, files: partialResult.files,
cssInlinedResources: cssInlinedResources, cssInlinedResources: cssInlinedResources,
bundleData: partialResult.bundleData bundleData: partialResult.bundleData
}); });
}, function (err) { return callback(err, null); }); }, (err) => callback(err, null));
} }
exports.bundle = bundle; exports.bundle = bundle;
function emitEntryPoints(modules, entryPoints) { function emitEntryPoints(modules, entryPoints) {
var modulesMap = {}; const modulesMap = {};
modules.forEach(function (m) { modules.forEach((m) => {
modulesMap[m.id] = m; modulesMap[m.id] = m;
}); });
var modulesGraph = {}; const modulesGraph = {};
modules.forEach(function (m) { modules.forEach((m) => {
modulesGraph[m.id] = m.dependencies; modulesGraph[m.id] = m.dependencies;
}); });
var sortedModules = topologicalSort(modulesGraph); const sortedModules = topologicalSort(modulesGraph);
var result = []; let result = [];
var usedPlugins = {}; const usedPlugins = {};
var bundleData = { const bundleData = {
graph: modulesGraph, graph: modulesGraph,
bundles: {} bundles: {}
}; };
Object.keys(entryPoints).forEach(function (moduleToBundle) { Object.keys(entryPoints).forEach((moduleToBundle) => {
var info = entryPoints[moduleToBundle]; const info = entryPoints[moduleToBundle];
var rootNodes = [moduleToBundle].concat(info.include || []); const rootNodes = [moduleToBundle].concat(info.include || []);
var allDependencies = visit(rootNodes, modulesGraph); const allDependencies = visit(rootNodes, modulesGraph);
var excludes = ['require', 'exports', 'module'].concat(info.exclude || []); const excludes = ['require', 'exports', 'module'].concat(info.exclude || []);
excludes.forEach(function (excludeRoot) { excludes.forEach((excludeRoot) => {
var allExcludes = visit([excludeRoot], modulesGraph); const allExcludes = visit([excludeRoot], modulesGraph);
Object.keys(allExcludes).forEach(function (exclude) { Object.keys(allExcludes).forEach((exclude) => {
delete allDependencies[exclude]; delete allDependencies[exclude];
}); });
}); });
var includedModules = sortedModules.filter(function (module) { const includedModules = sortedModules.filter((module) => {
return allDependencies[module]; return allDependencies[module];
}); });
bundleData.bundles[moduleToBundle] = includedModules; bundleData.bundles[moduleToBundle] = includedModules;
var res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend, info.append, info.dest); const res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend || [], info.append || [], info.dest);
result = result.concat(res.files); result = result.concat(res.files);
for (var pluginName in res.usedPlugins) { for (const pluginName in res.usedPlugins) {
usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName]; usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName];
} }
}); });
Object.keys(usedPlugins).forEach(function (pluginName) { Object.keys(usedPlugins).forEach((pluginName) => {
var plugin = usedPlugins[pluginName]; const plugin = usedPlugins[pluginName];
if (typeof plugin.finishBuild === 'function') { if (typeof plugin.finishBuild === 'function') {
var write = function (filename, contents) { const write = (filename, contents) => {
result.push({ result.push({
dest: filename, dest: filename,
sources: [{ sources: [{
@@ -124,16 +128,16 @@ function emitEntryPoints(modules, entryPoints) {
}; };
} }
function extractStrings(destFiles) { function extractStrings(destFiles) {
var parseDefineCall = function (moduleMatch, depsMatch) { const parseDefineCall = (moduleMatch, depsMatch) => {
var module = moduleMatch.replace(/^"|"$/g, ''); const module = moduleMatch.replace(/^"|"$/g, '');
var deps = depsMatch.split(','); let deps = depsMatch.split(',');
deps = deps.map(function (dep) { deps = deps.map((dep) => {
dep = dep.trim(); dep = dep.trim();
dep = dep.replace(/^"|"$/g, ''); dep = dep.replace(/^"|"$/g, '');
dep = dep.replace(/^'|'$/g, ''); dep = dep.replace(/^'|'$/g, '');
var prefix = null; let prefix = null;
var _path = null; let _path = null;
var pieces = dep.split('!'); const pieces = dep.split('!');
if (pieces.length > 1) { if (pieces.length > 1) {
prefix = pieces[0] + '!'; prefix = pieces[0] + '!';
_path = pieces[1]; _path = pieces[1];
@@ -143,7 +147,7 @@ function extractStrings(destFiles) {
_path = pieces[0]; _path = pieces[0];
} }
if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) { if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) {
var res = path.join(path.dirname(module), _path).replace(/\\/g, '/'); const res = path.join(path.dirname(module), _path).replace(/\\/g, '/');
return prefix + res; return prefix + res;
} }
return prefix + _path; return prefix + _path;
@@ -153,7 +157,7 @@ function extractStrings(destFiles) {
deps: deps deps: deps
}; };
}; };
destFiles.forEach(function (destFile, index) { destFiles.forEach((destFile) => {
if (!/\.js$/.test(destFile.dest)) { if (!/\.js$/.test(destFile.dest)) {
return; return;
} }
@@ -161,44 +165,44 @@ function extractStrings(destFiles) {
return; return;
} }
// Do one pass to record the usage counts for each module id // Do one pass to record the usage counts for each module id
var useCounts = {}; const useCounts = {};
destFile.sources.forEach(function (source) { destFile.sources.forEach((source) => {
var matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/); const matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/);
if (!matches) { if (!matches) {
return; return;
} }
var defineCall = parseDefineCall(matches[1], matches[2]); const defineCall = parseDefineCall(matches[1], matches[2]);
useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1; useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1;
defineCall.deps.forEach(function (dep) { defineCall.deps.forEach((dep) => {
useCounts[dep] = (useCounts[dep] || 0) + 1; useCounts[dep] = (useCounts[dep] || 0) + 1;
}); });
}); });
var sortedByUseModules = Object.keys(useCounts); const sortedByUseModules = Object.keys(useCounts);
sortedByUseModules.sort(function (a, b) { sortedByUseModules.sort((a, b) => {
return useCounts[b] - useCounts[a]; return useCounts[b] - useCounts[a];
}); });
var replacementMap = {}; const replacementMap = {};
sortedByUseModules.forEach(function (module, index) { sortedByUseModules.forEach((module, index) => {
replacementMap[module] = index; replacementMap[module] = index;
}); });
destFile.sources.forEach(function (source) { destFile.sources.forEach((source) => {
source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, function (_, moduleMatch, depsMatch) { source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, (_, moduleMatch, depsMatch) => {
var defineCall = parseDefineCall(moduleMatch, depsMatch); const defineCall = parseDefineCall(moduleMatch, depsMatch);
return "define(__m[" + replacementMap[defineCall.module] + "/*" + defineCall.module + "*/], __M([" + defineCall.deps.map(function (dep) { return replacementMap[dep] + '/*' + dep + '*/'; }).join(',') + "])"; return `define(__m[${replacementMap[defineCall.module]}/*${defineCall.module}*/], __M([${defineCall.deps.map(dep => replacementMap[dep] + '/*' + dep + '*/').join(',')}])`;
}); });
}); });
destFile.sources.unshift({ destFile.sources.unshift({
path: null, path: null,
contents: [ contents: [
'(function() {', '(function() {',
"var __m = " + JSON.stringify(sortedByUseModules) + ";", `var __m = ${JSON.stringify(sortedByUseModules)};`,
"var __M = function(deps) {", `var __M = function(deps) {`,
" var result = [];", ` var result = [];`,
" for (var i = 0, len = deps.length; i < len; i++) {", ` for (var i = 0, len = deps.length; i < len; i++) {`,
" result[i] = __m[deps[i]];", ` result[i] = __m[deps[i]];`,
" }", ` }`,
" return result;", ` return result;`,
"};" `};`
].join('\n') ].join('\n')
}); });
destFile.sources.push({ destFile.sources.push({
@@ -210,7 +214,7 @@ function extractStrings(destFiles) {
} }
function removeDuplicateTSBoilerplate(destFiles) { function removeDuplicateTSBoilerplate(destFiles) {
// Taken from typescript compiler => emitFiles // Taken from typescript compiler => emitFiles
var BOILERPLATE = [ const BOILERPLATE = [
{ start: /^var __extends/, end: /^}\)\(\);$/ }, { start: /^var __extends/, end: /^}\)\(\);$/ },
{ start: /^var __assign/, end: /^};$/ }, { start: /^var __assign/, end: /^};$/ },
{ start: /^var __decorate/, end: /^};$/ }, { start: /^var __decorate/, end: /^};$/ },
@@ -219,14 +223,14 @@ function removeDuplicateTSBoilerplate(destFiles) {
{ start: /^var __awaiter/, end: /^};$/ }, { start: /^var __awaiter/, end: /^};$/ },
{ start: /^var __generator/, end: /^};$/ }, { start: /^var __generator/, end: /^};$/ },
]; ];
destFiles.forEach(function (destFile) { destFiles.forEach((destFile) => {
var SEEN_BOILERPLATE = []; const SEEN_BOILERPLATE = [];
destFile.sources.forEach(function (source) { destFile.sources.forEach((source) => {
var lines = source.contents.split(/\r\n|\n|\r/); const lines = source.contents.split(/\r\n|\n|\r/);
var newLines = []; const newLines = [];
var IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE; let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
for (var i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
var line = lines[i]; const line = lines[i];
if (IS_REMOVING_BOILERPLATE) { if (IS_REMOVING_BOILERPLATE) {
newLines.push(''); newLines.push('');
if (END_BOILERPLATE.test(line)) { if (END_BOILERPLATE.test(line)) {
@@ -234,8 +238,8 @@ function removeDuplicateTSBoilerplate(destFiles) {
} }
} }
else { else {
for (var j = 0; j < BOILERPLATE.length; j++) { for (let j = 0; j < BOILERPLATE.length; j++) {
var boilerplate = BOILERPLATE[j]; const boilerplate = BOILERPLATE[j];
if (boilerplate.start.test(line)) { if (boilerplate.start.test(line)) {
if (SEEN_BOILERPLATE[j]) { if (SEEN_BOILERPLATE[j]) {
IS_REMOVING_BOILERPLATE = true; IS_REMOVING_BOILERPLATE = true;
@@ -263,45 +267,45 @@ function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend,
if (!dest) { if (!dest) {
dest = entryPoint + '.js'; dest = entryPoint + '.js';
} }
var mainResult = { const mainResult = {
sources: [], sources: [],
dest: dest dest: dest
}, results = [mainResult]; }, results = [mainResult];
var usedPlugins = {}; const usedPlugins = {};
var getLoaderPlugin = function (pluginName) { const getLoaderPlugin = (pluginName) => {
if (!usedPlugins[pluginName]) { if (!usedPlugins[pluginName]) {
usedPlugins[pluginName] = modulesMap[pluginName].exports; usedPlugins[pluginName] = modulesMap[pluginName].exports;
} }
return usedPlugins[pluginName]; return usedPlugins[pluginName];
}; };
includedModules.forEach(function (c) { includedModules.forEach((c) => {
var bangIndex = c.indexOf('!'); const bangIndex = c.indexOf('!');
if (bangIndex >= 0) { if (bangIndex >= 0) {
var pluginName = c.substr(0, bangIndex); const pluginName = c.substr(0, bangIndex);
var plugin = getLoaderPlugin(pluginName); const plugin = getLoaderPlugin(pluginName);
mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1))); mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1)));
return; return;
} }
var module = modulesMap[c]; const module = modulesMap[c];
if (module.path === 'empty:') { if (module.path === 'empty:') {
return; return;
} }
var contents = readFileAndRemoveBOM(module.path); const contents = readFileAndRemoveBOM(module.path);
if (module.shim) { if (module.shim) {
mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents)); mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents));
} }
else { else {
mainResult.sources.push(emitNamedModule(c, deps[c], module.defineLocation, module.path, contents)); mainResult.sources.push(emitNamedModule(c, module.defineLocation, module.path, contents));
} }
}); });
Object.keys(usedPlugins).forEach(function (pluginName) { Object.keys(usedPlugins).forEach((pluginName) => {
var plugin = usedPlugins[pluginName]; const plugin = usedPlugins[pluginName];
if (typeof plugin.writeFile === 'function') { if (typeof plugin.writeFile === 'function') {
var req = (function () { const req = (() => {
throw new Error('no-no!'); throw new Error('no-no!');
}); });
req.toUrl = function (something) { return something; }; req.toUrl = something => something;
var write = function (filename, contents) { const write = (filename, contents) => {
results.push({ results.push({
dest: filename, dest: filename,
sources: [{ sources: [{
@@ -313,15 +317,15 @@ function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend,
plugin.writeFile(pluginName, entryPoint, req, write, {}); plugin.writeFile(pluginName, entryPoint, req, write, {});
} }
}); });
var toIFile = function (path) { const toIFile = (path) => {
var contents = readFileAndRemoveBOM(path); const contents = readFileAndRemoveBOM(path);
return { return {
path: path, path: path,
contents: contents contents: contents
}; };
}; };
var toPrepend = (prepend || []).map(toIFile); const toPrepend = (prepend || []).map(toIFile);
var toAppend = (append || []).map(toIFile); const toAppend = (append || []).map(toIFile);
mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend); mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend);
return { return {
files: results, files: results,
@@ -329,8 +333,8 @@ function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend,
}; };
} }
function readFileAndRemoveBOM(path) { function readFileAndRemoveBOM(path) {
var BOM_CHAR_CODE = 65279; const BOM_CHAR_CODE = 65279;
var contents = fs.readFileSync(path, 'utf8'); let contents = fs.readFileSync(path, 'utf8');
// Remove BOM // Remove BOM
if (contents.charCodeAt(0) === BOM_CHAR_CODE) { if (contents.charCodeAt(0) === BOM_CHAR_CODE) {
contents = contents.substring(1); contents = contents.substring(1);
@@ -338,15 +342,15 @@ function readFileAndRemoveBOM(path) {
return contents; return contents;
} }
function emitPlugin(entryPoint, plugin, pluginName, moduleName) { function emitPlugin(entryPoint, plugin, pluginName, moduleName) {
var result = ''; let result = '';
if (typeof plugin.write === 'function') { if (typeof plugin.write === 'function') {
var write = (function (what) { const write = ((what) => {
result += what; result += what;
}); });
write.getEntryPoint = function () { write.getEntryPoint = () => {
return entryPoint; return entryPoint;
}; };
write.asModule = function (moduleId, code) { write.asModule = (moduleId, code) => {
code = code.replace(/^define\(/, 'define("' + moduleId + '",'); code = code.replace(/^define\(/, 'define("' + moduleId + '",');
result += code; result += code;
}; };
@@ -357,20 +361,20 @@ function emitPlugin(entryPoint, plugin, pluginName, moduleName) {
contents: result contents: result
}; };
} }
function emitNamedModule(moduleId, myDeps, defineCallPosition, path, contents) { function emitNamedModule(moduleId, defineCallPosition, path, contents) {
// `defineCallPosition` is the position in code: |define() // `defineCallPosition` is the position in code: |define()
var defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col); const defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col);
// `parensOffset` is the position in code: define|() // `parensOffset` is the position in code: define|()
var parensOffset = contents.indexOf('(', defineCallOffset); const parensOffset = contents.indexOf('(', defineCallOffset);
var insertStr = '"' + moduleId + '", '; const insertStr = '"' + moduleId + '", ';
return { return {
path: path, path: path,
contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1) contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1)
}; };
} }
function emitShimmedModule(moduleId, myDeps, factory, path, contents) { function emitShimmedModule(moduleId, myDeps, factory, path, contents) {
var strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : ''); const strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : '');
var strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');'; const strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');';
return { return {
path: path, path: path,
contents: contents + '\n;\n' + strDefine contents: contents + '\n;\n' + strDefine
@@ -383,7 +387,8 @@ function positionToOffset(str, desiredLine, desiredCol) {
if (desiredLine === 1) { if (desiredLine === 1) {
return desiredCol - 1; return desiredCol - 1;
} }
var line = 1, lastNewLineOffset = -1; let line = 1;
let lastNewLineOffset = -1;
do { do {
if (desiredLine === line) { if (desiredLine === line) {
return lastNewLineOffset + 1 + desiredCol - 1; return lastNewLineOffset + 1 + desiredCol - 1;
@@ -397,14 +402,15 @@ function positionToOffset(str, desiredLine, desiredCol) {
* Return a set of reachable nodes in `graph` starting from `rootNodes` * Return a set of reachable nodes in `graph` starting from `rootNodes`
*/ */
function visit(rootNodes, graph) { function visit(rootNodes, graph) {
var result = {}, queue = rootNodes; const result = {};
rootNodes.forEach(function (node) { const queue = rootNodes;
rootNodes.forEach((node) => {
result[node] = true; result[node] = true;
}); });
while (queue.length > 0) { while (queue.length > 0) {
var el = queue.shift(); const el = queue.shift();
var myEdges = graph[el] || []; const myEdges = graph[el] || [];
myEdges.forEach(function (toNode) { myEdges.forEach((toNode) => {
if (!result[toNode]) { if (!result[toNode]) {
result[toNode] = true; result[toNode] = true;
queue.push(toNode); queue.push(toNode);
@@ -417,11 +423,11 @@ function visit(rootNodes, graph) {
* Perform a topological sort on `graph` * Perform a topological sort on `graph`
*/ */
function topologicalSort(graph) { function topologicalSort(graph) {
var allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {}; const allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {};
Object.keys(graph).forEach(function (fromNode) { Object.keys(graph).forEach((fromNode) => {
allNodes[fromNode] = true; allNodes[fromNode] = true;
outgoingEdgeCount[fromNode] = graph[fromNode].length; outgoingEdgeCount[fromNode] = graph[fromNode].length;
graph[fromNode].forEach(function (toNode) { graph[fromNode].forEach((toNode) => {
allNodes[toNode] = true; allNodes[toNode] = true;
outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0; outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0;
inverseEdges[toNode] = inverseEdges[toNode] || []; inverseEdges[toNode] = inverseEdges[toNode] || [];
@@ -429,8 +435,8 @@ function topologicalSort(graph) {
}); });
}); });
// https://en.wikipedia.org/wiki/Topological_sorting // https://en.wikipedia.org/wiki/Topological_sorting
var S = [], L = []; const S = [], L = [];
Object.keys(allNodes).forEach(function (node) { Object.keys(allNodes).forEach((node) => {
if (outgoingEdgeCount[node] === 0) { if (outgoingEdgeCount[node] === 0) {
delete outgoingEdgeCount[node]; delete outgoingEdgeCount[node];
S.push(node); S.push(node);
@@ -439,10 +445,10 @@ function topologicalSort(graph) {
while (S.length > 0) { while (S.length > 0) {
// Ensure the exact same order all the time with the same inputs // Ensure the exact same order all the time with the same inputs
S.sort(); S.sort();
var n = S.shift(); const n = S.shift();
L.push(n); L.push(n);
var myInverseEdges = inverseEdges[n] || []; const myInverseEdges = inverseEdges[n] || [];
myInverseEdges.forEach(function (m) { myInverseEdges.forEach((m) => {
outgoingEdgeCount[m]--; outgoingEdgeCount[m]--;
if (outgoingEdgeCount[m] === 0) { if (outgoingEdgeCount[m] === 0) {
delete outgoingEdgeCount[m]; delete outgoingEdgeCount[m];

View File

@@ -3,9 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import fs = require('fs'); import * as fs from 'fs';
import path = require('path'); import * as path from 'path';
import vm = require('vm'); import * as vm from 'vm';
interface IPosition { interface IPosition {
line: number; line: number;
@@ -46,7 +46,7 @@ export interface IEntryPoint {
name: string; name: string;
include?: string[]; include?: string[];
exclude?: string[]; exclude?: string[];
prepend: string[]; prepend?: string[];
append?: string[]; append?: string[];
dest?: string; dest?: string;
} }
@@ -64,7 +64,7 @@ interface INodeSet {
} }
export interface IFile { export interface IFile {
path: string; path: string | null;
contents: string; contents: string;
} }
@@ -97,13 +97,13 @@ export interface ILoaderConfig {
/** /**
* Bundle `entryPoints` given config `config`. * Bundle `entryPoints` given config `config`.
*/ */
export function bundle(entryPoints: IEntryPoint[], config: ILoaderConfig, callback: (err: any, result: IBundleResult) => void): void { export function bundle(entryPoints: IEntryPoint[], config: ILoaderConfig, callback: (err: any, result: IBundleResult | null) => void): void {
let entryPointsMap: IEntryPointMap = {}; const entryPointsMap: IEntryPointMap = {};
entryPoints.forEach((module: IEntryPoint) => { entryPoints.forEach((module: IEntryPoint) => {
entryPointsMap[module.name] = module; entryPointsMap[module.name] = module;
}); });
let allMentionedModulesMap: { [modules: string]: boolean; } = {}; const allMentionedModulesMap: { [modules: string]: boolean; } = {};
entryPoints.forEach((module: IEntryPoint) => { entryPoints.forEach((module: IEntryPoint) => {
allMentionedModulesMap[module.name] = true; allMentionedModulesMap[module.name] = true;
(module.include || []).forEach(function (includedModule) { (module.include || []).forEach(function (includedModule) {
@@ -115,28 +115,32 @@ export function bundle(entryPoints: IEntryPoint[], config: ILoaderConfig, callba
}); });
var code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js')); const code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js'));
var r: Function = <any>vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});'); const r: Function = <any>vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});');
var loaderModule = { exports: {} }; const loaderModule = { exports: {} };
r.call({}, require, loaderModule, loaderModule.exports); r.call({}, require, loaderModule, loaderModule.exports);
var loader: any = loaderModule.exports; const loader: any = loaderModule.exports;
config.isBuild = true; config.isBuild = true;
config.paths = config.paths || {}; config.paths = config.paths || {};
config.paths['vs/nls'] = 'out-build/vs/nls.build'; if (!config.paths['vs/nls']) {
config.paths['vs/css'] = 'out-build/vs/css.build'; config.paths['vs/nls'] = 'out-build/vs/nls.build';
}
if (!config.paths['vs/css']) {
config.paths['vs/css'] = 'out-build/vs/css.build';
}
loader.config(config); loader.config(config);
loader(['require'], (localRequire) => { loader(['require'], (localRequire: any) => {
let resolvePath = (path: string) => { const resolvePath = (path: string) => {
let r = localRequire.toUrl(path); const r = localRequire.toUrl(path);
if (!/\.js/.test(r)) { if (!/\.js/.test(r)) {
return r + '.js'; return r + '.js';
} }
return r; return r;
}; };
for (let moduleId in entryPointsMap) { for (const moduleId in entryPointsMap) {
let entryPoint = entryPointsMap[moduleId]; const entryPoint = entryPointsMap[moduleId];
if (entryPoint.append) { if (entryPoint.append) {
entryPoint.append = entryPoint.append.map(resolvePath); entryPoint.append = entryPoint.append.map(resolvePath);
} }
@@ -147,76 +151,76 @@ export function bundle(entryPoints: IEntryPoint[], config: ILoaderConfig, callba
}); });
loader(Object.keys(allMentionedModulesMap), () => { loader(Object.keys(allMentionedModulesMap), () => {
let modules = <IBuildModuleInfo[]>loader.getBuildInfo(); const modules = <IBuildModuleInfo[]>loader.getBuildInfo();
let partialResult = emitEntryPoints(modules, entryPointsMap); const partialResult = emitEntryPoints(modules, entryPointsMap);
let cssInlinedResources = loader('vs/css').getInlinedResources(); const cssInlinedResources = loader('vs/css').getInlinedResources();
callback(null, { callback(null, {
files: partialResult.files, files: partialResult.files,
cssInlinedResources: cssInlinedResources, cssInlinedResources: cssInlinedResources,
bundleData: partialResult.bundleData bundleData: partialResult.bundleData
}); });
}, (err) => callback(err, null)); }, (err: any) => callback(err, null));
} }
function emitEntryPoints(modules: IBuildModuleInfo[], entryPoints: IEntryPointMap): IPartialBundleResult { function emitEntryPoints(modules: IBuildModuleInfo[], entryPoints: IEntryPointMap): IPartialBundleResult {
let modulesMap: IBuildModuleInfoMap = {}; const modulesMap: IBuildModuleInfoMap = {};
modules.forEach((m: IBuildModuleInfo) => { modules.forEach((m: IBuildModuleInfo) => {
modulesMap[m.id] = m; modulesMap[m.id] = m;
}); });
let modulesGraph: IGraph = {}; const modulesGraph: IGraph = {};
modules.forEach((m: IBuildModuleInfo) => { modules.forEach((m: IBuildModuleInfo) => {
modulesGraph[m.id] = m.dependencies; modulesGraph[m.id] = m.dependencies;
}); });
let sortedModules = topologicalSort(modulesGraph); const sortedModules = topologicalSort(modulesGraph);
let result: IConcatFile[] = []; let result: IConcatFile[] = [];
let usedPlugins: IPluginMap = {}; const usedPlugins: IPluginMap = {};
let bundleData: IBundleData = { const bundleData: IBundleData = {
graph: modulesGraph, graph: modulesGraph,
bundles: {} bundles: {}
}; };
Object.keys(entryPoints).forEach((moduleToBundle: string) => { Object.keys(entryPoints).forEach((moduleToBundle: string) => {
let info = entryPoints[moduleToBundle]; const info = entryPoints[moduleToBundle];
let rootNodes = [moduleToBundle].concat(info.include || []); const rootNodes = [moduleToBundle].concat(info.include || []);
let allDependencies = visit(rootNodes, modulesGraph); const allDependencies = visit(rootNodes, modulesGraph);
let excludes: string[] = ['require', 'exports', 'module'].concat(info.exclude || []); const excludes: string[] = ['require', 'exports', 'module'].concat(info.exclude || []);
excludes.forEach((excludeRoot: string) => { excludes.forEach((excludeRoot: string) => {
let allExcludes = visit([excludeRoot], modulesGraph); const allExcludes = visit([excludeRoot], modulesGraph);
Object.keys(allExcludes).forEach((exclude: string) => { Object.keys(allExcludes).forEach((exclude: string) => {
delete allDependencies[exclude]; delete allDependencies[exclude];
}); });
}); });
let includedModules = sortedModules.filter((module: string) => { const includedModules = sortedModules.filter((module: string) => {
return allDependencies[module]; return allDependencies[module];
}); });
bundleData.bundles[moduleToBundle] = includedModules; bundleData.bundles[moduleToBundle] = includedModules;
let res = emitEntryPoint( const res = emitEntryPoint(
modulesMap, modulesMap,
modulesGraph, modulesGraph,
moduleToBundle, moduleToBundle,
includedModules, includedModules,
info.prepend, info.prepend || [],
info.append, info.append || [],
info.dest info.dest
); );
result = result.concat(res.files); result = result.concat(res.files);
for (let pluginName in res.usedPlugins) { for (const pluginName in res.usedPlugins) {
usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName]; usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName];
} }
}); });
Object.keys(usedPlugins).forEach((pluginName: string) => { Object.keys(usedPlugins).forEach((pluginName: string) => {
let plugin = usedPlugins[pluginName]; const plugin = usedPlugins[pluginName];
if (typeof plugin.finishBuild === 'function') { if (typeof plugin.finishBuild === 'function') {
let write = (filename: string, contents: string) => { const write = (filename: string, contents: string) => {
result.push({ result.push({
dest: filename, dest: filename,
sources: [{ sources: [{
@@ -237,16 +241,16 @@ function emitEntryPoints(modules: IBuildModuleInfo[], entryPoints: IEntryPointMa
} }
function extractStrings(destFiles: IConcatFile[]): IConcatFile[] { function extractStrings(destFiles: IConcatFile[]): IConcatFile[] {
let parseDefineCall = (moduleMatch: string, depsMatch: string) => { const parseDefineCall = (moduleMatch: string, depsMatch: string) => {
let module = moduleMatch.replace(/^"|"$/g, ''); const module = moduleMatch.replace(/^"|"$/g, '');
let deps = depsMatch.split(','); let deps = depsMatch.split(',');
deps = deps.map((dep) => { deps = deps.map((dep) => {
dep = dep.trim(); dep = dep.trim();
dep = dep.replace(/^"|"$/g, ''); dep = dep.replace(/^"|"$/g, '');
dep = dep.replace(/^'|'$/g, ''); dep = dep.replace(/^'|'$/g, '');
let prefix: string = null; let prefix: string | null = null;
let _path: string = null; let _path: string | null = null;
let pieces = dep.split('!'); const pieces = dep.split('!');
if (pieces.length > 1) { if (pieces.length > 1) {
prefix = pieces[0] + '!'; prefix = pieces[0] + '!';
_path = pieces[1]; _path = pieces[1];
@@ -256,7 +260,7 @@ function extractStrings(destFiles: IConcatFile[]): IConcatFile[] {
} }
if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) { if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) {
let res = path.join(path.dirname(module), _path).replace(/\\/g, '/'); const res = path.join(path.dirname(module), _path).replace(/\\/g, '/');
return prefix + res; return prefix + res;
} }
return prefix + _path; return prefix + _path;
@@ -267,7 +271,7 @@ function extractStrings(destFiles: IConcatFile[]): IConcatFile[] {
}; };
}; };
destFiles.forEach((destFile, index) => { destFiles.forEach((destFile) => {
if (!/\.js$/.test(destFile.dest)) { if (!/\.js$/.test(destFile.dest)) {
return; return;
} }
@@ -276,33 +280,33 @@ function extractStrings(destFiles: IConcatFile[]): IConcatFile[] {
} }
// Do one pass to record the usage counts for each module id // Do one pass to record the usage counts for each module id
let useCounts: { [moduleId: string]: number; } = {}; const useCounts: { [moduleId: string]: number; } = {};
destFile.sources.forEach((source) => { destFile.sources.forEach((source) => {
let matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/); const matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/);
if (!matches) { if (!matches) {
return; return;
} }
let defineCall = parseDefineCall(matches[1], matches[2]); const defineCall = parseDefineCall(matches[1], matches[2]);
useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1; useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1;
defineCall.deps.forEach((dep) => { defineCall.deps.forEach((dep) => {
useCounts[dep] = (useCounts[dep] || 0) + 1; useCounts[dep] = (useCounts[dep] || 0) + 1;
}); });
}); });
let sortedByUseModules = Object.keys(useCounts); const sortedByUseModules = Object.keys(useCounts);
sortedByUseModules.sort((a, b) => { sortedByUseModules.sort((a, b) => {
return useCounts[b] - useCounts[a]; return useCounts[b] - useCounts[a];
}); });
let replacementMap: { [moduleId: string]: number; } = {}; const replacementMap: { [moduleId: string]: number; } = {};
sortedByUseModules.forEach((module, index) => { sortedByUseModules.forEach((module, index) => {
replacementMap[module] = index; replacementMap[module] = index;
}); });
destFile.sources.forEach((source) => { destFile.sources.forEach((source) => {
source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, (_, moduleMatch, depsMatch) => { source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, (_, moduleMatch, depsMatch) => {
let defineCall = parseDefineCall(moduleMatch, depsMatch); const defineCall = parseDefineCall(moduleMatch, depsMatch);
return `define(__m[${replacementMap[defineCall.module]}/*${defineCall.module}*/], __M([${defineCall.deps.map(dep => replacementMap[dep] + '/*' + dep + '*/').join(',')}])`; return `define(__m[${replacementMap[defineCall.module]}/*${defineCall.module}*/], __M([${defineCall.deps.map(dep => replacementMap[dep] + '/*' + dep + '*/').join(',')}])`;
}); });
}); });
@@ -332,7 +336,7 @@ function extractStrings(destFiles: IConcatFile[]): IConcatFile[] {
function removeDuplicateTSBoilerplate(destFiles: IConcatFile[]): IConcatFile[] { function removeDuplicateTSBoilerplate(destFiles: IConcatFile[]): IConcatFile[] {
// Taken from typescript compiler => emitFiles // Taken from typescript compiler => emitFiles
let BOILERPLATE = [ const BOILERPLATE = [
{ start: /^var __extends/, end: /^}\)\(\);$/ }, { start: /^var __extends/, end: /^}\)\(\);$/ },
{ start: /^var __assign/, end: /^};$/ }, { start: /^var __assign/, end: /^};$/ },
{ start: /^var __decorate/, end: /^};$/ }, { start: /^var __decorate/, end: /^};$/ },
@@ -343,22 +347,22 @@ function removeDuplicateTSBoilerplate(destFiles: IConcatFile[]): IConcatFile[] {
]; ];
destFiles.forEach((destFile) => { destFiles.forEach((destFile) => {
let SEEN_BOILERPLATE = []; const SEEN_BOILERPLATE: boolean[] = [];
destFile.sources.forEach((source) => { destFile.sources.forEach((source) => {
let lines = source.contents.split(/\r\n|\n|\r/); const lines = source.contents.split(/\r\n|\n|\r/);
let newLines: string[] = []; const newLines: string[] = [];
let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE: RegExp; let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE: RegExp;
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
let line = lines[i]; const line = lines[i];
if (IS_REMOVING_BOILERPLATE) { if (IS_REMOVING_BOILERPLATE) {
newLines.push(''); newLines.push('');
if (END_BOILERPLATE.test(line)) { if (END_BOILERPLATE!.test(line)) {
IS_REMOVING_BOILERPLATE = false; IS_REMOVING_BOILERPLATE = false;
} }
} else { } else {
for (let j = 0; j < BOILERPLATE.length; j++) { for (let j = 0; j < BOILERPLATE.length; j++) {
let boilerplate = BOILERPLATE[j]; const boilerplate = BOILERPLATE[j];
if (boilerplate.start.test(line)) { if (boilerplate.start.test(line)) {
if (SEEN_BOILERPLATE[j]) { if (SEEN_BOILERPLATE[j]) {
IS_REMOVING_BOILERPLATE = true; IS_REMOVING_BOILERPLATE = true;
@@ -398,19 +402,19 @@ function emitEntryPoint(
includedModules: string[], includedModules: string[],
prepend: string[], prepend: string[],
append: string[], append: string[],
dest: string dest: string | undefined
): IEmitEntryPointResult { ): IEmitEntryPointResult {
if (!dest) { if (!dest) {
dest = entryPoint + '.js'; dest = entryPoint + '.js';
} }
let mainResult: IConcatFile = { const mainResult: IConcatFile = {
sources: [], sources: [],
dest: dest dest: dest
}, },
results: IConcatFile[] = [mainResult]; results: IConcatFile[] = [mainResult];
let usedPlugins: IPluginMap = {}; const usedPlugins: IPluginMap = {};
let getLoaderPlugin = (pluginName: string): ILoaderPlugin => { const getLoaderPlugin = (pluginName: string): ILoaderPlugin => {
if (!usedPlugins[pluginName]) { if (!usedPlugins[pluginName]) {
usedPlugins[pluginName] = modulesMap[pluginName].exports; usedPlugins[pluginName] = modulesMap[pluginName].exports;
} }
@@ -418,39 +422,39 @@ function emitEntryPoint(
}; };
includedModules.forEach((c: string) => { includedModules.forEach((c: string) => {
let bangIndex = c.indexOf('!'); const bangIndex = c.indexOf('!');
if (bangIndex >= 0) { if (bangIndex >= 0) {
let pluginName = c.substr(0, bangIndex); const pluginName = c.substr(0, bangIndex);
let plugin = getLoaderPlugin(pluginName); const plugin = getLoaderPlugin(pluginName);
mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1))); mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1)));
return; return;
} }
let module = modulesMap[c]; const module = modulesMap[c];
if (module.path === 'empty:') { if (module.path === 'empty:') {
return; return;
} }
let contents = readFileAndRemoveBOM(module.path); const contents = readFileAndRemoveBOM(module.path);
if (module.shim) { if (module.shim) {
mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents)); mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents));
} else { } else {
mainResult.sources.push(emitNamedModule(c, deps[c], module.defineLocation, module.path, contents)); mainResult.sources.push(emitNamedModule(c, module.defineLocation, module.path, contents));
} }
}); });
Object.keys(usedPlugins).forEach((pluginName: string) => { Object.keys(usedPlugins).forEach((pluginName: string) => {
let plugin = usedPlugins[pluginName]; const plugin = usedPlugins[pluginName];
if (typeof plugin.writeFile === 'function') { if (typeof plugin.writeFile === 'function') {
let req: ILoaderPluginReqFunc = <any>(() => { const req: ILoaderPluginReqFunc = <any>(() => {
throw new Error('no-no!'); throw new Error('no-no!');
}); });
req.toUrl = something => something; req.toUrl = something => something;
let write = (filename: string, contents: string) => { const write = (filename: string, contents: string) => {
results.push({ results.push({
dest: filename, dest: filename,
sources: [{ sources: [{
@@ -463,16 +467,16 @@ function emitEntryPoint(
} }
}); });
let toIFile = (path): IFile => { const toIFile = (path: string): IFile => {
let contents = readFileAndRemoveBOM(path); const contents = readFileAndRemoveBOM(path);
return { return {
path: path, path: path,
contents: contents contents: contents
}; };
}; };
let toPrepend = (prepend || []).map(toIFile); const toPrepend = (prepend || []).map(toIFile);
let toAppend = (append || []).map(toIFile); const toAppend = (append || []).map(toIFile);
mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend); mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend);
@@ -483,8 +487,8 @@ function emitEntryPoint(
} }
function readFileAndRemoveBOM(path: string): string { function readFileAndRemoveBOM(path: string): string {
var BOM_CHAR_CODE = 65279; const BOM_CHAR_CODE = 65279;
var contents = fs.readFileSync(path, 'utf8'); let contents = fs.readFileSync(path, 'utf8');
// Remove BOM // Remove BOM
if (contents.charCodeAt(0) === BOM_CHAR_CODE) { if (contents.charCodeAt(0) === BOM_CHAR_CODE) {
contents = contents.substring(1); contents = contents.substring(1);
@@ -495,7 +499,7 @@ function readFileAndRemoveBOM(path: string): string {
function emitPlugin(entryPoint: string, plugin: ILoaderPlugin, pluginName: string, moduleName: string): IFile { function emitPlugin(entryPoint: string, plugin: ILoaderPlugin, pluginName: string, moduleName: string): IFile {
let result = ''; let result = '';
if (typeof plugin.write === 'function') { if (typeof plugin.write === 'function') {
let write: ILoaderPluginWriteFunc = <any>((what) => { const write: ILoaderPluginWriteFunc = <any>((what: string) => {
result += what; result += what;
}); });
write.getEntryPoint = () => { write.getEntryPoint = () => {
@@ -513,15 +517,15 @@ function emitPlugin(entryPoint: string, plugin: ILoaderPlugin, pluginName: strin
}; };
} }
function emitNamedModule(moduleId: string, myDeps: string[], defineCallPosition: IPosition, path: string, contents: string): IFile { function emitNamedModule(moduleId: string, defineCallPosition: IPosition, path: string, contents: string): IFile {
// `defineCallPosition` is the position in code: |define() // `defineCallPosition` is the position in code: |define()
let defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col); const defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col);
// `parensOffset` is the position in code: define|() // `parensOffset` is the position in code: define|()
let parensOffset = contents.indexOf('(', defineCallOffset); const parensOffset = contents.indexOf('(', defineCallOffset);
let insertStr = '"' + moduleId + '", '; const insertStr = '"' + moduleId + '", ';
return { return {
path: path, path: path,
@@ -530,8 +534,8 @@ function emitNamedModule(moduleId: string, myDeps: string[], defineCallPosition:
} }
function emitShimmedModule(moduleId: string, myDeps: string[], factory: string, path: string, contents: string): IFile { function emitShimmedModule(moduleId: string, myDeps: string[], factory: string, path: string, contents: string): IFile {
let strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : ''); const strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : '');
let strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');'; const strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');';
return { return {
path: path, path: path,
contents: contents + '\n;\n' + strDefine contents: contents + '\n;\n' + strDefine
@@ -546,8 +550,8 @@ function positionToOffset(str: string, desiredLine: number, desiredCol: number):
return desiredCol - 1; return desiredCol - 1;
} }
let line = 1, let line = 1;
lastNewLineOffset = -1; let lastNewLineOffset = -1;
do { do {
if (desiredLine === line) { if (desiredLine === line) {
@@ -565,16 +569,16 @@ function positionToOffset(str: string, desiredLine: number, desiredCol: number):
* Return a set of reachable nodes in `graph` starting from `rootNodes` * Return a set of reachable nodes in `graph` starting from `rootNodes`
*/ */
function visit(rootNodes: string[], graph: IGraph): INodeSet { function visit(rootNodes: string[], graph: IGraph): INodeSet {
let result: INodeSet = {}, const result: INodeSet = {};
queue = rootNodes; const queue = rootNodes;
rootNodes.forEach((node) => { rootNodes.forEach((node) => {
result[node] = true; result[node] = true;
}); });
while (queue.length > 0) { while (queue.length > 0) {
let el = queue.shift(); const el = queue.shift();
let myEdges = graph[el] || []; const myEdges = graph[el!] || [];
myEdges.forEach((toNode) => { myEdges.forEach((toNode) => {
if (!result[toNode]) { if (!result[toNode]) {
result[toNode] = true; result[toNode] = true;
@@ -591,7 +595,7 @@ function visit(rootNodes: string[], graph: IGraph): INodeSet {
*/ */
function topologicalSort(graph: IGraph): string[] { function topologicalSort(graph: IGraph): string[] {
let allNodes: INodeSet = {}, const allNodes: INodeSet = {},
outgoingEdgeCount: { [node: string]: number; } = {}, outgoingEdgeCount: { [node: string]: number; } = {},
inverseEdges: IGraph = {}; inverseEdges: IGraph = {};
@@ -609,7 +613,7 @@ function topologicalSort(graph: IGraph): string[] {
}); });
// https://en.wikipedia.org/wiki/Topological_sorting // https://en.wikipedia.org/wiki/Topological_sorting
let S: string[] = [], const S: string[] = [],
L: string[] = []; L: string[] = [];
Object.keys(allNodes).forEach((node: string) => { Object.keys(allNodes).forEach((node: string) => {
@@ -623,10 +627,10 @@ function topologicalSort(graph: IGraph): string[] {
// Ensure the exact same order all the time with the same inputs // Ensure the exact same order all the time with the same inputs
S.sort(); S.sort();
let n: string = S.shift(); const n: string = S.shift()!;
L.push(n); L.push(n);
let myInverseEdges = inverseEdges[n] || []; const myInverseEdges = inverseEdges[n] || [];
myInverseEdges.forEach((m: string) => { myInverseEdges.forEach((m: string) => {
outgoingEdgeCount[m]--; outgoingEdgeCount[m]--;
if (outgoingEdgeCount[m] === 0) { if (outgoingEdgeCount[m] === 0) {

View File

@@ -4,44 +4,53 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var gulp = require("gulp"); const es = require("event-stream");
var tsb = require("gulp-tsb"); const fs = require("fs");
var es = require("event-stream"); const gulp = require("gulp");
var watch = require('./watch'); const bom = require("gulp-bom");
var nls = require("./nls"); const sourcemaps = require("gulp-sourcemaps");
var util = require("./util"); const tsb = require("gulp-tsb");
var reporter_1 = require("./reporter"); const path = require("path");
var path = require("path"); const _ = require("underscore");
var bom = require("gulp-bom"); const monacodts = require("../monaco/api");
var sourcemaps = require("gulp-sourcemaps"); const nls = require("./nls");
var _ = require("underscore"); const reporter_1 = require("./reporter");
var monacodts = require("../monaco/api"); const util = require("./util");
var fs = require("fs"); const util2 = require("gulp-util");
var reporter = reporter_1.createReporter(); const watch = require('./watch');
const reporter = reporter_1.createReporter();
function getTypeScriptCompilerOptions(src) { function getTypeScriptCompilerOptions(src) {
var rootDir = path.join(__dirname, "../../" + src); const rootDir = path.join(__dirname, `../../${src}`);
var options = require("../../" + src + "/tsconfig.json").compilerOptions; const tsconfig = require(`../../${src}/tsconfig.json`);
let options;
if (tsconfig.extends) {
options = Object.assign({}, require(path.join(rootDir, tsconfig.extends)).compilerOptions, tsconfig.compilerOptions);
}
else {
options = tsconfig.compilerOptions;
}
options.verbose = false; options.verbose = false;
options.sourceMap = true; options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
options.sourceMap = false; options.sourceMap = false;
} }
options.rootDir = rootDir; options.rootDir = rootDir;
options.baseUrl = rootDir;
options.sourceRoot = util.toFileUri(rootDir); options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF'; options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF';
return options; return options;
} }
function createCompile(src, build, emitError) { function createCompile(src, build, emitError) {
var opts = _.clone(getTypeScriptCompilerOptions(src)); const opts = _.clone(getTypeScriptCompilerOptions(src));
opts.inlineSources = !!build; opts.inlineSources = !!build;
opts.noFilesystemLookup = true; opts.noFilesystemLookup = true;
var ts = tsb.create(opts, null, null, function (err) { return reporter(err.toString()); }); const ts = tsb.create(opts, true, undefined, err => reporter(err.toString()));
return function (token) { return function (token) {
var utf8Filter = util.filter(function (data) { return /(\/|\\)test(\/|\\).*utf8/.test(data.path); }); const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path));
var tsFilter = util.filter(function (data) { return /\.ts$/.test(data.path); }); const tsFilter = util.filter(data => /\.ts$/.test(data.path));
var noDeclarationsFilter = util.filter(function (data) { return !(/\.d\.ts$/.test(data.path)); }); const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path)));
var input = es.through(); const input = es.through();
var output = input const output = input
.pipe(utf8Filter) .pipe(utf8Filter)
.pipe(bom()) .pipe(bom())
.pipe(utf8Filter.restore) .pipe(utf8Filter.restore)
@@ -57,91 +66,122 @@ function createCompile(src, build, emitError) {
sourceRoot: opts.sourceRoot sourceRoot: opts.sourceRoot
})) }))
.pipe(tsFilter.restore) .pipe(tsFilter.restore)
.pipe(reporter.end(emitError)); .pipe(reporter.end(!!emitError));
return es.duplex(input, output); return es.duplex(input, output);
}; };
} }
const typesDts = [
'node_modules/typescript/lib/*.d.ts',
'node_modules/@types/**/*.d.ts',
'!node_modules/@types/webpack/**/*',
'!node_modules/@types/uglify-js/**/*',
];
function compileTask(src, out, build) { function compileTask(src, out, build) {
return function () { return function () {
var compile = createCompile(src, build, true); const compile = createCompile(src, build, true);
var srcPipe = es.merge(gulp.src(src + "/**", { base: "" + src }), gulp.src('node_modules/typescript/lib/lib.d.ts')); const srcPipe = es.merge(gulp.src(`${src}/**`, { base: `${src}` }), gulp.src(typesDts));
// Do not write .d.ts files to disk, as they are not needed there. let generator = new MonacoGenerator(false);
var dtsFilter = util.filter(function (data) { return !/\.d\.ts$/.test(data.path); }); if (src === 'src') {
generator.execute();
}
return srcPipe return srcPipe
.pipe(generator.stream)
.pipe(compile()) .pipe(compile())
.pipe(dtsFilter) .pipe(gulp.dest(out));
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(src !== 'src' ? es.through() : monacodtsTask(out, false));
}; };
} }
exports.compileTask = compileTask; exports.compileTask = compileTask;
function watchTask(out, build) { function watchTask(out, build) {
return function () { return function () {
var compile = createCompile('src', build); const compile = createCompile('src', build);
var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts')); const src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src(typesDts));
var watchSrc = watch('src/**', { base: 'src' }); const watchSrc = watch('src/**', { base: 'src' });
// Do not write .d.ts files to disk, as they are not needed there. let generator = new MonacoGenerator(true);
var dtsFilter = util.filter(function (data) { return !/\.d\.ts$/.test(data.path); }); generator.execute();
return watchSrc return watchSrc
.pipe(generator.stream)
.pipe(util.incremental(compile, src, true)) .pipe(util.incremental(compile, src, true))
.pipe(dtsFilter) .pipe(gulp.dest(out));
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, true));
}; };
} }
exports.watchTask = watchTask; exports.watchTask = watchTask;
function monacodtsTask(out, isWatch) { const REPO_SRC_FOLDER = path.join(__dirname, '../../src');
var basePath = path.resolve(process.cwd(), out); class MonacoGenerator {
var neededFiles = {}; constructor(isWatch) {
monacodts.getFilesToWatch(out).forEach(function (filePath) { this._executeSoonTimer = null;
filePath = path.normalize(filePath); this._isWatch = isWatch;
neededFiles[filePath] = true; this.stream = es.through();
}); this._watchers = [];
var inputFiles = {}; this._watchedFiles = {};
for (var filePath in neededFiles) { let onWillReadFile = (moduleId, filePath) => {
if (/\bsrc(\/|\\)vs\b/.test(filePath)) { if (!this._isWatch) {
// This file is needed from source => simply read it now return;
inputFiles[filePath] = fs.readFileSync(filePath).toString(); }
if (this._watchedFiles[filePath]) {
return;
}
this._watchedFiles[filePath] = true;
const watcher = fs.watch(filePath);
watcher.addListener('change', () => {
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
this._watchers.push(watcher);
};
this._fsProvider = new class extends monacodts.FSProvider {
readFileSync(moduleId, filePath) {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
const recipeWatcher = fs.watch(monacodts.RECIPE_PATH);
recipeWatcher.addListener('change', () => {
this._executeSoon();
});
this._watchers.push(recipeWatcher);
} }
} }
var setInputFile = function (filePath, contents) { _executeSoon() {
if (inputFiles[filePath] === contents) { if (this._executeSoonTimer !== null) {
// no change clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
this.execute();
}, 20);
}
dispose() {
this._watchers.forEach(watcher => watcher.close());
}
_run() {
let r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
_log(message, ...rest) {
util2.log(util2.colors.cyan('[monaco.d.ts]'), message, ...rest);
}
execute() {
const startTime = Date.now();
const result = this._run();
if (!result) {
// nothing really changed
return; return;
} }
inputFiles[filePath] = contents; if (result.isTheSame) {
var neededInputFilesCount = Object.keys(neededFiles).length; return;
var availableInputFilesCount = Object.keys(inputFiles).length;
if (neededInputFilesCount === availableInputFilesCount) {
run();
} }
}; fs.writeFileSync(result.filePath, result.content);
var run = function () { fs.writeFileSync(path.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
var result = monacodts.run(out, inputFiles); this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`);
if (!result.isTheSame) { if (!this._isWatch) {
if (isWatch) { this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
fs.writeFileSync(result.filePath, result.content);
}
else {
fs.writeFileSync(result.filePath, result.content);
resultStream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
}
} }
};
var resultStream;
if (isWatch) {
watch('build/monaco/*').pipe(es.through(function () {
run();
}));
} }
resultStream = es.through(function (data) {
var filePath = path.normalize(path.resolve(basePath, data.relative));
if (neededFiles[filePath]) {
setInputFile(filePath, data.contents.toString());
}
this.emit('data', data);
});
return resultStream;
} }

View File

@@ -5,31 +5,39 @@
'use strict'; 'use strict';
import * as gulp from 'gulp';
import * as tsb from 'gulp-tsb';
import * as es from 'event-stream'; import * as es from 'event-stream';
const watch = require('./watch'); import * as fs from 'fs';
import * as nls from './nls'; import * as gulp from 'gulp';
import * as util from './util';
import { createReporter } from './reporter';
import * as path from 'path';
import * as bom from 'gulp-bom'; import * as bom from 'gulp-bom';
import * as sourcemaps from 'gulp-sourcemaps'; import * as sourcemaps from 'gulp-sourcemaps';
import * as tsb from 'gulp-tsb';
import * as path from 'path';
import * as _ from 'underscore'; import * as _ from 'underscore';
import * as monacodts from '../monaco/api'; import * as monacodts from '../monaco/api';
import * as fs from 'fs'; import * as nls from './nls';
import { createReporter } from './reporter';
import * as util from './util';
import * as util2 from 'gulp-util';
const watch = require('./watch');
const reporter = createReporter(); const reporter = createReporter();
function getTypeScriptCompilerOptions(src: string) { function getTypeScriptCompilerOptions(src: string) {
const rootDir = path.join(__dirname, `../../${src}`); const rootDir = path.join(__dirname, `../../${src}`);
const options = require(`../../${src}/tsconfig.json`).compilerOptions; const tsconfig = require(`../../${src}/tsconfig.json`);
let options: { [key: string]: any };
if (tsconfig.extends) {
options = Object.assign({}, require(path.join(rootDir, tsconfig.extends)).compilerOptions, tsconfig.compilerOptions);
} else {
options = tsconfig.compilerOptions;
}
options.verbose = false; options.verbose = false;
options.sourceMap = true; options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
options.sourceMap = false; options.sourceMap = false;
} }
options.rootDir = rootDir; options.rootDir = rootDir;
options.baseUrl = rootDir;
options.sourceRoot = util.toFileUri(rootDir); options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF'; options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF';
return options; return options;
@@ -40,7 +48,7 @@ function createCompile(src: string, build: boolean, emitError?: boolean): (token
opts.inlineSources = !!build; opts.inlineSources = !!build;
opts.noFilesystemLookup = true; opts.noFilesystemLookup = true;
const ts = tsb.create(opts, null, null, err => reporter(err.toString())); const ts = tsb.create(opts, true, undefined, err => reporter(err.toString()));
return function (token?: util.ICancellationToken) { return function (token?: util.ICancellationToken) {
@@ -65,12 +73,19 @@ function createCompile(src: string, build: boolean, emitError?: boolean): (token
sourceRoot: opts.sourceRoot sourceRoot: opts.sourceRoot
})) }))
.pipe(tsFilter.restore) .pipe(tsFilter.restore)
.pipe(reporter.end(emitError)); .pipe(reporter.end(!!emitError));
return es.duplex(input, output); return es.duplex(input, output);
}; };
} }
const typesDts = [
'node_modules/typescript/lib/*.d.ts',
'node_modules/@types/**/*.d.ts',
'!node_modules/@types/webpack/**/*',
'!node_modules/@types/uglify-js/**/*',
];
export function compileTask(src: string, out: string, build: boolean): () => NodeJS.ReadWriteStream { export function compileTask(src: string, out: string, build: boolean): () => NodeJS.ReadWriteStream {
return function () { return function () {
@@ -78,18 +93,18 @@ export function compileTask(src: string, out: string, build: boolean): () => Nod
const srcPipe = es.merge( const srcPipe = es.merge(
gulp.src(`${src}/**`, { base: `${src}` }), gulp.src(`${src}/**`, { base: `${src}` }),
gulp.src('node_modules/typescript/lib/lib.d.ts'), gulp.src(typesDts),
); );
// Do not write .d.ts files to disk, as they are not needed there. let generator = new MonacoGenerator(false);
const dtsFilter = util.filter(data => !/\.d\.ts$/.test(data.path)); if (src === 'src') {
generator.execute();
}
return srcPipe return srcPipe
.pipe(generator.stream)
.pipe(compile()) .pipe(compile())
.pipe(dtsFilter) .pipe(gulp.dest(out));
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(src !== 'src' ? es.through() : monacodtsTask(out, false));
}; };
} }
@@ -100,80 +115,114 @@ export function watchTask(out: string, build: boolean): () => NodeJS.ReadWriteSt
const src = es.merge( const src = es.merge(
gulp.src('src/**', { base: 'src' }), gulp.src('src/**', { base: 'src' }),
gulp.src('node_modules/typescript/lib/lib.d.ts'), gulp.src(typesDts),
); );
const watchSrc = watch('src/**', { base: 'src' }); const watchSrc = watch('src/**', { base: 'src' });
// Do not write .d.ts files to disk, as they are not needed there. let generator = new MonacoGenerator(true);
const dtsFilter = util.filter(data => !/\.d\.ts$/.test(data.path)); generator.execute();
return watchSrc return watchSrc
.pipe(generator.stream)
.pipe(util.incremental(compile, src, true)) .pipe(util.incremental(compile, src, true))
.pipe(dtsFilter) .pipe(gulp.dest(out));
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, true));
}; };
} }
function monacodtsTask(out: string, isWatch: boolean): NodeJS.ReadWriteStream { const REPO_SRC_FOLDER = path.join(__dirname, '../../src');
const basePath = path.resolve(process.cwd(), out); class MonacoGenerator {
private readonly _isWatch: boolean;
public readonly stream: NodeJS.ReadWriteStream;
const neededFiles: { [file: string]: boolean; } = {}; private readonly _watchers: fs.FSWatcher[];
monacodts.getFilesToWatch(out).forEach(function (filePath) { private readonly _watchedFiles: { [filePath: string]: boolean; };
filePath = path.normalize(filePath); private readonly _fsProvider: monacodts.FSProvider;
neededFiles[filePath] = true; private readonly _declarationResolver: monacodts.DeclarationResolver;
});
const inputFiles: { [file: string]: string; } = {}; constructor(isWatch: boolean) {
for (let filePath in neededFiles) { this._isWatch = isWatch;
if (/\bsrc(\/|\\)vs\b/.test(filePath)) { this.stream = es.through();
// This file is needed from source => simply read it now this._watchers = [];
inputFiles[filePath] = fs.readFileSync(filePath).toString(); this._watchedFiles = {};
let onWillReadFile = (moduleId: string, filePath: string) => {
if (!this._isWatch) {
return;
}
if (this._watchedFiles[filePath]) {
return;
}
this._watchedFiles[filePath] = true;
const watcher = fs.watch(filePath);
watcher.addListener('change', () => {
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
this._watchers.push(watcher);
};
this._fsProvider = new class extends monacodts.FSProvider {
public readFileSync(moduleId: string, filePath: string): Buffer {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
const recipeWatcher = fs.watch(monacodts.RECIPE_PATH);
recipeWatcher.addListener('change', () => {
this._executeSoon();
});
this._watchers.push(recipeWatcher);
} }
} }
const setInputFile = (filePath: string, contents: string) => { private _executeSoonTimer: NodeJS.Timer | null = null;
if (inputFiles[filePath] === contents) { private _executeSoon(): void {
// no change if (this._executeSoonTimer !== null) {
clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
this.execute();
}, 20);
}
public dispose(): void {
this._watchers.forEach(watcher => watcher.close());
}
private _run(): monacodts.IMonacoDeclarationResult | null {
let r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
private _log(message: any, ...rest: any[]): void {
util2.log(util2.colors.cyan('[monaco.d.ts]'), message, ...rest);
}
public execute(): void {
const startTime = Date.now();
const result = this._run();
if (!result) {
// nothing really changed
return; return;
} }
inputFiles[filePath] = contents; if (result.isTheSame) {
const neededInputFilesCount = Object.keys(neededFiles).length; return;
const availableInputFilesCount = Object.keys(inputFiles).length;
if (neededInputFilesCount === availableInputFilesCount) {
run();
} }
};
const run = () => { fs.writeFileSync(result.filePath, result.content);
const result = monacodts.run(out, inputFiles); fs.writeFileSync(path.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
if (!result.isTheSame) { this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`);
if (isWatch) { if (!this._isWatch) {
fs.writeFileSync(result.filePath, result.content); this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
} else {
fs.writeFileSync(result.filePath, result.content);
resultStream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
}
} }
};
let resultStream: NodeJS.ReadWriteStream;
if (isWatch) {
watch('build/monaco/*').pipe(es.through(function () {
run();
}));
} }
resultStream = es.through(function (data) {
const filePath = path.normalize(path.resolve(basePath, data.relative));
if (neededFiles[filePath]) {
setInputFile(filePath, data.contents.toString());
}
this.emit('data', data);
});
return resultStream;
} }

View File

@@ -11,6 +11,7 @@ const root = path.dirname(path.dirname(__dirname));
function getElectronVersion() { function getElectronVersion() {
const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8'); const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
// @ts-ignore
const target = /^target "(.*)"$/m.exec(yarnrc)[1]; const target = /^target "(.*)"$/m.exec(yarnrc)[1];
return target; return target;
@@ -19,6 +20,7 @@ function getElectronVersion() {
module.exports.getElectronVersion = getElectronVersion; module.exports.getElectronVersion = getElectronVersion;
// returns 0 if the right version of electron is in .build/electron // returns 0 if the right version of electron is in .build/electron
// @ts-ignore
if (require.main === module) { if (require.main === module) {
const version = getElectronVersion(); const version = getElectronVersion();
const versionFile = path.join(root, '.build', 'electron', 'version'); const versionFile = path.join(root, '.build', 'electron', 'version');

View File

@@ -4,116 +4,317 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var es = require("event-stream"); const es = require("event-stream");
var assign = require("object-assign"); const fs = require("fs");
var remote = require("gulp-remote-src"); const glob = require("glob");
var flatmap = require('gulp-flatmap'); const gulp = require("gulp");
var vzip = require('gulp-vinyl-zip'); const path = require("path");
var filter = require('gulp-filter'); const File = require("vinyl");
var rename = require('gulp-rename'); const vsce = require("vsce");
var util = require('gulp-util'); const stats_1 = require("./stats");
var buffer = require('gulp-buffer'); const util2 = require("./util");
var json = require('gulp-json-editor'); const remote = require("gulp-remote-src");
var fs = require("fs"); const vzip = require('gulp-vinyl-zip');
var path = require("path"); const filter = require("gulp-filter");
var vsce = require("vsce"); const rename = require("gulp-rename");
var File = require("vinyl"); const util = require('gulp-util');
function fromLocal(extensionPath) { const buffer = require('gulp-buffer');
var result = es.through(); const json = require("gulp-json-editor");
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn }) const webpack = require('webpack');
.then(function (fileNames) { const webpackGulp = require('webpack-stream');
var files = fileNames const root = path.resolve(path.join(__dirname, '..', '..'));
.map(function (fileName) { return path.join(extensionPath, fileName); }) // {{SQL CARBON EDIT}}
.map(function (filePath) { return new File({ const _ = require("underscore");
const vfs = require("vinyl-fs");
const deps = require('../dependencies');
const extensionsRoot = path.join(root, 'extensions');
const extensionsProductionDependencies = deps.getProductionDependencies(extensionsRoot);
function packageBuiltInExtensions() {
const sqlBuiltInLocalExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0);
sqlBuiltInLocalExtensionDescriptions.forEach(element => {
const packagePath = path.join(path.dirname(root), element.name + '.vsix');
console.info('Creating vsix for ' + element.path + ' result:' + packagePath);
vsce.createVSIX({
cwd: element.path,
packagePath: packagePath,
useYarn: true
});
});
}
exports.packageBuiltInExtensions = packageBuiltInExtensions;
function packageExtensionTask(extensionName, platform, arch) {
var destination = path.join(path.dirname(root), 'azuredatastudio') + (platform ? '-' + platform : '') + (arch ? '-' + arch : '');
if (platform === 'darwin') {
destination = path.join(destination, 'Azure Data Studio.app', 'Contents', 'Resources', 'app', 'extensions', extensionName);
}
else {
destination = path.join(destination, 'resources', 'app', 'extensions', extensionName);
}
platform = platform || process.platform;
return () => {
const root = path.resolve(path.join(__dirname, '../..'));
const localExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => extensionName === name);
const localExtensions = es.merge(...localExtensionDescriptions.map(extension => {
return fromLocal(extension.path);
}));
let result = localExtensions
.pipe(util2.skipDirectories())
.pipe(util2.fixWin32DirectoryPermissions())
.pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version']));
return result.pipe(vfs.dest(destination));
};
}
exports.packageExtensionTask = packageExtensionTask;
// {{SQL CARBON EDIT}} - End
function fromLocal(extensionPath, sourceMappingURLBase) {
const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js');
if (fs.existsSync(webpackFilename)) {
return fromLocalWebpack(extensionPath, sourceMappingURLBase);
}
else {
return fromLocalNormal(extensionPath);
}
}
function fromLocalWebpack(extensionPath, sourceMappingURLBase) {
const result = es.through();
const packagedDependencies = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path.join(extensionPath, 'extension.webpack.config.js'));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
packagedDependencies.push(key);
}
}
}
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath, path: filePath,
stat: fs.statSync(filePath), stat: fs.statSync(filePath),
base: extensionPath, base: extensionPath,
contents: fs.createReadStream(filePath) contents: fs.createReadStream(filePath)
}); }); }));
const filesStream = es.readArray(files);
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream. also rewrite the package.json
// file to a new entry point
const webpackConfigLocations = glob.sync(path.join(extensionPath, '/**/extension.webpack.config.js'), { ignore: ['**/node_modules'] });
const packageJsonFilter = filter(f => {
if (path.basename(f.path) === 'package.json') {
// only modify package.json's next to the webpack file.
// to be safe, use existsSync instead of path comparison.
return fs.existsSync(path.join(path.dirname(f.path), 'extension.webpack.config.js'));
}
return false;
}, { restore: true });
const patchFilesStream = filesStream
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json((data) => {
if (data.main) {
// hardcoded entry point directory!
data.main = data.main.replace('/out/', /dist/);
}
return data;
}))
.pipe(packageJsonFilter.restore);
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => () => {
const webpackDone = (err, stats) => {
util.log(`Bundled extension: ${util.colors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
result.emit('error', err);
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('error', compilation.warnings.join('\n'));
}
};
const webpackConfig = Object.assign({}, require(webpackConfigPath), { mode: 'production' });
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(es.through(function (data) {
data.stat = data.stat || {};
data.base = extensionPath;
this.emit('data', data);
}))
.pipe(es.through(function (data) {
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
if (sourceMappingURLBase) {
const contents = data.contents.toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
}), 'utf8');
if (/\.js\.map$/.test(data.path)) {
if (!fs.existsSync(path.dirname(data.path))) {
fs.mkdirSync(path.dirname(data.path));
}
fs.writeFileSync(data.path, data.contents);
}
}
this.emit('data', data);
}));
});
es.merge(sequence(webpackStreams), patchFilesStream)
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
.pipe(result);
}).catch(err => {
console.error(extensionPath);
console.error(packagedDependencies);
result.emit('error', err);
});
return result.pipe(stats_1.createStatsStream(path.basename(extensionPath)));
}
function fromLocalNormal(extensionPath) {
const result = es.through();
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn })
.then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath)
}));
es.readArray(files).pipe(result); es.readArray(files).pipe(result);
}) })
.catch(function (err) { return result.emit('error', err); }); .catch(err => result.emit('error', err));
return result; return result.pipe(stats_1.createStatsStream(path.basename(extensionPath)));
} }
exports.fromLocal = fromLocal; const baseHeaders = {
function error(err) {
var result = es.through();
setTimeout(function () { return result.emit('error', err); });
return result;
}
var baseHeaders = {
'X-Market-Client-Id': 'VSCode Build', 'X-Market-Client-Id': 'VSCode Build',
'User-Agent': 'VSCode Build', 'User-Agent': 'VSCode Build',
'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2', 'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2',
}; };
function fromMarketplace(extensionName, version) { function fromMarketplace(extensionName, version, metadata) {
var filterType = 7; const [publisher, name] = extensionName.split('.');
var value = extensionName; const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`;
var criterium = { filterType: filterType, value: value }; util.log('Downloading extension:', util.colors.yellow(`${extensionName}@${version}`), '...');
var criteria = [criterium]; const options = {
var pageNumber = 1; base: url,
var pageSize = 1;
var sortBy = 0;
var sortOrder = 0;
var flags = 0x1 | 0x2 | 0x80;
var assetTypes = ['Microsoft.VisualStudio.Services.VSIXPackage'];
var filters = [{ criteria: criteria, pageNumber: pageNumber, pageSize: pageSize, sortBy: sortBy, sortOrder: sortOrder }];
var body = JSON.stringify({ filters: filters, assetTypes: assetTypes, flags: flags });
var headers = assign({}, baseHeaders, {
'Content-Type': 'application/json',
'Accept': 'application/json;api-version=3.0-preview.1',
'Content-Length': body.length
});
var options = {
base: 'https://marketplace.visualstudio.com/_apis/public/gallery',
requestOptions: { requestOptions: {
method: 'POST',
gzip: true, gzip: true,
headers: headers, headers: baseHeaders
body: body
} }
}; };
return remote('/extensionquery', options) const packageJsonFilter = filter('package.json', { restore: true });
.pipe(flatmap(function (stream, f) { return remote('', options)
var rawResult = f.contents.toString('utf8'); .pipe(vzip.src())
var result = JSON.parse(rawResult); .pipe(filter('extension/**'))
var extension = result.results[0].extensions[0]; .pipe(rename(p => p.dirname = p.dirname.replace(/^extension\/?/, '')))
if (!extension) { .pipe(packageJsonFilter)
return error("No such extension: " + extension); .pipe(buffer())
} .pipe(json({ __metadata: metadata }))
var metadata = { .pipe(packageJsonFilter.restore);
id: extension.extensionId,
publisherId: extension.publisher,
publisherDisplayName: extension.publisher.displayName
};
var extensionVersion = extension.versions.filter(function (v) { return v.version === version; })[0];
if (!extensionVersion) {
return error("No such extension version: " + extensionName + " @ " + version);
}
var asset = extensionVersion.files.filter(function (f) { return f.assetType === 'Microsoft.VisualStudio.Services.VSIXPackage'; })[0];
if (!asset) {
return error("No VSIX found for extension version: " + extensionName + " @ " + version);
}
util.log('Downloading extension:', util.colors.yellow(extensionName + "@" + version), '...');
var options = {
base: asset.source,
requestOptions: {
gzip: true,
headers: baseHeaders
}
};
return remote('', options)
.pipe(flatmap(function (stream) {
var packageJsonFilter = filter('package.json', { restore: true });
return stream
.pipe(vzip.src())
.pipe(filter('extension/**'))
.pipe(rename(function (p) { return p.dirname = p.dirname.replace(/^extension\/?/, ''); }))
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}));
}));
} }
exports.fromMarketplace = fromMarketplace; exports.fromMarketplace = fromMarketplace;
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}}
'integration-tests'
];
// {{SQL CARBON EDIT}}
const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
// the extension will be excluded from SQLOps package and will have separate vsix packages
'agent',
'import',
'profiler',
'admin-pack',
'big-data-cluster',
'dacpac'
];
var azureExtensions = ['azurecore', 'mssql'];
const builtInExtensions = require('../builtInExtensions.json');
/**
* We're doing way too much stuff at once, with webpack et al. So much stuff
* that while downloading extensions from the marketplace, node js doesn't get enough
* stack frames to complete the download in under 2 minutes, at which point the
* marketplace server cuts off the http request. So, we sequentialize the extensino tasks.
*/
function sequence(streamProviders) {
const result = es.through();
function pop() {
if (streamProviders.length === 0) {
result.emit('end');
}
else {
const fn = streamProviders.shift();
fn()
.on('end', function () { setTimeout(pop, 0); })
.pipe(result, { end: false });
}
}
pop();
return result;
}
function packageExtensionsStream(optsIn) {
const opts = optsIn || {};
const localExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
// {{SQL CARBON EDIT}}
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
return fromLocal(extension.path, opts.sourceMappingURLBase)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
})]);
// {{SQL CARBON EDIT}}
const extensionDepsSrc = [
..._.flatten(extensionsProductionDependencies.map((d) => path.relative(root, d.path)).map((d) => [`${d}/**`, `!${d}/**/{test,tests}/**`])),
];
const localExtensionDependencies = () => gulp.src(extensionDepsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
.pipe(util2.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util2.cleanNodeModule('typescript', ['**/**'], undefined));
// Original code commented out here
// const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' });
// const marketplaceExtensions = () => es.merge(
// ...builtInExtensions
// .filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
// .map(extension => {
// return fromMarketplace(extension.name, extension.version, extension.metadata)
// .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
// })
// );
return sequence([localExtensions, localExtensionDependencies,])
.pipe(util2.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', '!**/*.js.map']));
// {{SQL CARBON EDIT}} - End
}
exports.packageExtensionsStream = packageExtensionsStream;

View File

@@ -4,22 +4,221 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as es from 'event-stream'; import * as es from 'event-stream';
import * as fs from 'fs';
import * as glob from 'glob';
import * as gulp from 'gulp';
import * as path from 'path';
import { Stream } from 'stream'; import { Stream } from 'stream';
import assign = require('object-assign'); import * as File from 'vinyl';
import * as vsce from 'vsce';
import { createStatsStream } from './stats';
import * as util2 from './util';
import remote = require('gulp-remote-src'); import remote = require('gulp-remote-src');
const flatmap = require('gulp-flatmap');
const vzip = require('gulp-vinyl-zip'); const vzip = require('gulp-vinyl-zip');
const filter = require('gulp-filter'); import filter = require('gulp-filter');
const rename = require('gulp-rename'); import rename = require('gulp-rename');
const util = require('gulp-util'); const util = require('gulp-util');
const buffer = require('gulp-buffer'); const buffer = require('gulp-buffer');
const json = require('gulp-json-editor'); import json = require('gulp-json-editor');
import * as fs from 'fs'; const webpack = require('webpack');
import * as path from 'path'; const webpackGulp = require('webpack-stream');
import * as vsce from 'vsce';
import * as File from 'vinyl';
export function fromLocal(extensionPath: string): Stream { const root = path.resolve(path.join(__dirname, '..', '..'));
// {{SQL CARBON EDIT}}
import * as _ from 'underscore';
import * as vfs from 'vinyl-fs';
const deps = require('../dependencies');
const extensionsRoot = path.join(root, 'extensions');
const extensionsProductionDependencies = deps.getProductionDependencies(extensionsRoot);
export function packageBuiltInExtensions() {
const sqlBuiltInLocalExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0);
sqlBuiltInLocalExtensionDescriptions.forEach(element => {
const packagePath = path.join(path.dirname(root), element.name + '.vsix');
console.info('Creating vsix for ' + element.path + ' result:' + packagePath);
vsce.createVSIX({
cwd: element.path,
packagePath: packagePath,
useYarn: true
});
});
}
export function packageExtensionTask(extensionName: string, platform: string, arch: string) {
var destination = path.join(path.dirname(root), 'azuredatastudio') + (platform ? '-' + platform : '') + (arch ? '-' + arch : '');
if (platform === 'darwin') {
destination = path.join(destination, 'Azure Data Studio.app', 'Contents', 'Resources', 'app', 'extensions', extensionName);
} else {
destination = path.join(destination, 'resources', 'app', 'extensions', extensionName);
}
platform = platform || process.platform;
return () => {
const root = path.resolve(path.join(__dirname, '../..'));
const localExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => extensionName === name);
const localExtensions = es.merge(...localExtensionDescriptions.map(extension => {
return fromLocal(extension.path);
}));
let result = localExtensions
.pipe(util2.skipDirectories())
.pipe(util2.fixWin32DirectoryPermissions())
.pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version']));
return result.pipe(vfs.dest(destination));
};
}
// {{SQL CARBON EDIT}} - End
function fromLocal(extensionPath: string, sourceMappingURLBase?: string): Stream {
const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js');
if (fs.existsSync(webpackFilename)) {
return fromLocalWebpack(extensionPath, sourceMappingURLBase);
} else {
return fromLocalNormal(extensionPath);
}
}
function fromLocalWebpack(extensionPath: string, sourceMappingURLBase: string | undefined): Stream {
const result = es.through();
const packagedDependencies: string[] = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path.join(extensionPath, 'extension.webpack.config.js'));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
packagedDependencies.push(key);
}
}
}
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath) as any
}));
const filesStream = es.readArray(files);
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream. also rewrite the package.json
// file to a new entry point
const webpackConfigLocations = (<string[]>glob.sync(
path.join(extensionPath, '/**/extension.webpack.config.js'),
{ ignore: ['**/node_modules'] }
));
const packageJsonFilter = filter(f => {
if (path.basename(f.path) === 'package.json') {
// only modify package.json's next to the webpack file.
// to be safe, use existsSync instead of path comparison.
return fs.existsSync(path.join(path.dirname(f.path), 'extension.webpack.config.js'));
}
return false;
}, { restore: true });
const patchFilesStream = filesStream
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json((data: any) => {
if (data.main) {
// hardcoded entry point directory!
data.main = data.main.replace('/out/', /dist/);
}
return data;
}))
.pipe(packageJsonFilter.restore);
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => () => {
const webpackDone = (err: any, stats: any) => {
util.log(`Bundled extension: ${util.colors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
result.emit('error', err);
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('error', compilation.warnings.join('\n'));
}
};
const webpackConfig = {
...require(webpackConfigPath),
...{ mode: 'production' }
};
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(es.through(function (data) {
data.stat = data.stat || {};
data.base = extensionPath;
this.emit('data', data);
}))
.pipe(es.through(function (data: File) {
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
if (sourceMappingURLBase) {
const contents = (<Buffer>data.contents).toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
}), 'utf8');
if (/\.js\.map$/.test(data.path)) {
if (!fs.existsSync(path.dirname(data.path))) {
fs.mkdirSync(path.dirname(data.path));
}
fs.writeFileSync(data.path, data.contents);
}
}
this.emit('data', data);
}));
});
es.merge(sequence(webpackStreams), patchFilesStream)
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
.pipe(result);
}).catch(err => {
console.error(extensionPath);
console.error(packagedDependencies);
result.emit('error', err);
});
return result.pipe(createStatsStream(path.basename(extensionPath)));
}
function fromLocalNormal(extensionPath: string): Stream {
const result = es.through(); const result = es.through();
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn }) vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn })
@@ -37,13 +236,7 @@ export function fromLocal(extensionPath: string): Stream {
}) })
.catch(err => result.emit('error', err)); .catch(err => result.emit('error', err));
return result; return result.pipe(createStatsStream(path.basename(extensionPath)));
}
function error(err: any): Stream {
const result = es.through();
setTimeout(() => result.emit('error', err));
return result;
} }
const baseHeaders = { const baseHeaders = {
@@ -52,82 +245,141 @@ const baseHeaders = {
'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2', 'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2',
}; };
export function fromMarketplace(extensionName: string, version: string): Stream { export function fromMarketplace(extensionName: string, version: string, metadata: any): Stream {
const filterType = 7; const [publisher, name] = extensionName.split('.');
const value = extensionName; const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`;
const criterium = { filterType, value };
const criteria = [criterium]; util.log('Downloading extension:', util.colors.yellow(`${extensionName}@${version}`), '...');
const pageNumber = 1;
const pageSize = 1;
const sortBy = 0;
const sortOrder = 0;
const flags = 0x1 | 0x2 | 0x80;
const assetTypes = ['Microsoft.VisualStudio.Services.VSIXPackage'];
const filters = [{ criteria, pageNumber, pageSize, sortBy, sortOrder }];
const body = JSON.stringify({ filters, assetTypes, flags });
const headers: any = assign({}, baseHeaders, {
'Content-Type': 'application/json',
'Accept': 'application/json;api-version=3.0-preview.1',
'Content-Length': body.length
});
const options = { const options = {
base: 'https://marketplace.visualstudio.com/_apis/public/gallery', base: url,
requestOptions: { requestOptions: {
method: 'POST',
gzip: true, gzip: true,
headers, headers: baseHeaders
body: body
} }
}; };
return remote('/extensionquery', options) const packageJsonFilter = filter('package.json', { restore: true });
.pipe(flatmap((stream, f) => {
const rawResult = f.contents.toString('utf8');
const result = JSON.parse(rawResult);
const extension = result.results[0].extensions[0];
if (!extension) {
return error(`No such extension: ${extension}`);
}
const metadata = { return remote('', options)
id: extension.extensionId, .pipe(vzip.src())
publisherId: extension.publisher, .pipe(filter('extension/**'))
publisherDisplayName: extension.publisher.displayName .pipe(rename(p => p.dirname = p.dirname!.replace(/^extension\/?/, '')))
}; .pipe(packageJsonFilter)
.pipe(buffer())
const extensionVersion = extension.versions.filter(v => v.version === version)[0]; .pipe(json({ __metadata: metadata }))
if (!extensionVersion) { .pipe(packageJsonFilter.restore);
return error(`No such extension version: ${extensionName} @ ${version}`); }
}
interface IPackageExtensionsOptions {
const asset = extensionVersion.files.filter(f => f.assetType === 'Microsoft.VisualStudio.Services.VSIXPackage')[0]; /**
if (!asset) { * Set to undefined to package all of them.
return error(`No VSIX found for extension version: ${extensionName} @ ${version}`); */
} desiredExtensions?: string[];
sourceMappingURLBase?: string;
util.log('Downloading extension:', util.colors.yellow(`${extensionName}@${version}`), '...'); }
const options = { const excludedExtensions = [
base: asset.source, 'vscode-api-tests',
requestOptions: { 'vscode-colorize-tests',
gzip: true, 'ms-vscode.node-debug',
headers: baseHeaders 'ms-vscode.node-debug2',
} // {{SQL CARBON EDIT}}
}; 'integration-tests'
];
return remote('', options)
.pipe(flatmap(stream => { // {{SQL CARBON EDIT}}
const packageJsonFilter = filter('package.json', { restore: true }); const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
return stream // the extension will be excluded from SQLOps package and will have separate vsix packages
.pipe(vzip.src()) 'agent',
.pipe(filter('extension/**')) 'import',
.pipe(rename(p => p.dirname = p.dirname.replace(/^extension\/?/, ''))) 'profiler',
.pipe(packageJsonFilter) 'admin-pack',
.pipe(buffer()) 'big-data-cluster',
.pipe(json({ __metadata: metadata })) 'dacpac'
.pipe(packageJsonFilter.restore); ];
})); var azureExtensions = ['azurecore', 'mssql'];
})); // {{SQL CARBON EDIT}} - End
interface IBuiltInExtension {
name: string;
version: string;
repo: string;
metadata: any;
}
const builtInExtensions: IBuiltInExtension[] = require('../builtInExtensions.json');
/**
* We're doing way too much stuff at once, with webpack et al. So much stuff
* that while downloading extensions from the marketplace, node js doesn't get enough
* stack frames to complete the download in under 2 minutes, at which point the
* marketplace server cuts off the http request. So, we sequentialize the extensino tasks.
*/
function sequence(streamProviders: { (): Stream }[]): Stream {
const result = es.through();
function pop() {
if (streamProviders.length === 0) {
result.emit('end');
} else {
const fn = streamProviders.shift()!;
fn()
.on('end', function () { setTimeout(pop, 0); })
.pipe(result, { end: false });
}
}
pop();
return result;
}
export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): NodeJS.ReadWriteStream {
const opts = optsIn || {};
const localExtensionDescriptions = (<string[]>glob.sync('extensions/*/package.json'))
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
// {{SQL CARBON EDIT}}
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
return fromLocal(extension.path, opts.sourceMappingURLBase)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
})]);
// {{SQL CARBON EDIT}}
const extensionDepsSrc = [
..._.flatten(extensionsProductionDependencies.map((d: any) => path.relative(root, d.path)).map((d: any) => [`${d}/**`, `!${d}/**/{test,tests}/**`])),
];
const localExtensionDependencies = () => gulp.src(extensionDepsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
.pipe(util2.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util2.cleanNodeModule('typescript', ['**/**'], undefined));
// Original code commented out here
// const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' });
// const marketplaceExtensions = () => es.merge(
// ...builtInExtensions
// .filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
// .map(extension => {
// return fromMarketplace(extension.name, extension.version, extension.metadata)
// .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
// })
// );
return sequence([localExtensions, localExtensionDependencies, /*marketplaceExtensions*/])
.pipe(util2.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', '!**/*.js.map']));
// {{SQL CARBON EDIT}} - End
} }

View File

@@ -4,15 +4,15 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var path = require("path"); const path = require("path");
var fs = require("fs"); const fs = require("fs");
/** /**
* Returns the sha1 commit version of a repository or undefined in case of failure. * Returns the sha1 commit version of a repository or undefined in case of failure.
*/ */
function getVersion(repo) { function getVersion(repo) {
var git = path.join(repo, '.git'); const git = path.join(repo, '.git');
var headPath = path.join(git, 'HEAD'); const headPath = path.join(git, 'HEAD');
var head; let head;
try { try {
head = fs.readFileSync(headPath, 'utf8').trim(); head = fs.readFileSync(headPath, 'utf8').trim();
} }
@@ -22,29 +22,29 @@ function getVersion(repo) {
if (/^[0-9a-f]{40}$/i.test(head)) { if (/^[0-9a-f]{40}$/i.test(head)) {
return head; return head;
} }
var refMatch = /^ref: (.*)$/.exec(head); const refMatch = /^ref: (.*)$/.exec(head);
if (!refMatch) { if (!refMatch) {
return void 0; return void 0;
} }
var ref = refMatch[1]; const ref = refMatch[1];
var refPath = path.join(git, ref); const refPath = path.join(git, ref);
try { try {
return fs.readFileSync(refPath, 'utf8').trim(); return fs.readFileSync(refPath, 'utf8').trim();
} }
catch (e) { catch (e) {
// noop // noop
} }
var packedRefsPath = path.join(git, 'packed-refs'); const packedRefsPath = path.join(git, 'packed-refs');
var refsRaw; let refsRaw;
try { try {
refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim(); refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim();
} }
catch (e) { catch (e) {
return void 0; return void 0;
} }
var refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm; const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
var refsMatch; let refsMatch;
var refs = {}; let refs = {};
while (refsMatch = refsRegex.exec(refsRaw)) { while (refsMatch = refsRegex.exec(refsRaw)) {
refs[refsMatch[2]] = refsMatch[1]; refs[refsMatch[2]] = refsMatch[1];
} }

View File

@@ -10,7 +10,7 @@ import * as fs from 'fs';
/** /**
* Returns the sha1 commit version of a repository or undefined in case of failure. * Returns the sha1 commit version of a repository or undefined in case of failure.
*/ */
export function getVersion(repo: string): string { export function getVersion(repo: string): string | undefined {
const git = path.join(repo, '.git'); const git = path.join(repo, '.git');
const headPath = path.join(git, 'HEAD'); const headPath = path.join(git, 'HEAD');
let head: string; let head: string;
@@ -50,7 +50,7 @@ export function getVersion(repo: string): string {
} }
const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm; const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
let refsMatch: RegExpExecArray; let refsMatch: RegExpExecArray | null;
let refs: { [ref: string]: string } = {}; let refs: { [ref: string]: string } = {};
while (refsMatch = refsRegex.exec(refsRaw)) { while (refsMatch = refsRegex.exec(refsRaw)) {

File diff suppressed because it is too large Load Diff

View File

@@ -78,10 +78,6 @@
"name": "vs/workbench/parts/logs", "name": "vs/workbench/parts/logs",
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{
"name": "vs/workbench/parts/navigation",
"project": "vscode-workbench"
},
{ {
"name": "vs/workbench/parts/output", "name": "vs/workbench/parts/output",
"project": "vscode-workbench" "project": "vscode-workbench"
@@ -114,6 +110,10 @@
"name": "vs/workbench/parts/snippets", "name": "vs/workbench/parts/snippets",
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{
"name": "vs/workbench/parts/stats",
"project": "vscode-workbench"
},
{ {
"name": "vs/workbench/parts/surveys", "name": "vs/workbench/parts/surveys",
"project": "vscode-workbench" "project": "vscode-workbench"
@@ -166,6 +166,10 @@
"name": "vs/workbench/services/bulkEdit", "name": "vs/workbench/services/bulkEdit",
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{
"name": "vs/workbench/services/commands",
"project": "vscode-workbench"
},
{ {
"name": "vs/workbench/services/configuration", "name": "vs/workbench/services/configuration",
"project": "vscode-workbench" "project": "vscode-workbench"
@@ -210,6 +214,10 @@
"name": "vs/workbench/services/progress", "name": "vs/workbench/services/progress",
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{
"name": "vs/workbench/services/remote",
"project": "vscode-workbench"
},
{ {
"name": "vs/workbench/services/textfile", "name": "vs/workbench/services/textfile",
"project": "vscode-workbench" "project": "vscode-workbench"

View File

@@ -7,15 +7,15 @@ import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import { through, readable, ThroughStream } from 'event-stream'; import { through, readable, ThroughStream } from 'event-stream';
import File = require('vinyl'); import * as File from 'vinyl';
import * as Is from 'is'; import * as Is from 'is';
import * as xml2js from 'xml2js'; import * as xml2js from 'xml2js';
import * as glob from 'glob'; import * as glob from 'glob';
import * as https from 'https'; import * as https from 'https';
import * as gulp from 'gulp'; import * as gulp from 'gulp';
var util = require('gulp-util'); import * as util from 'gulp-util';
var iconv = require('iconv-lite'); import * as iconv from 'iconv-lite';
const NUMBER_OF_CONCURRENT_DOWNLOADS = 4; const NUMBER_OF_CONCURRENT_DOWNLOADS = 4;
@@ -57,7 +57,7 @@ export const extraLanguages: Language[] = [
]; ];
// non built-in extensions also that are transifex and need to be part of the language packs // non built-in extensions also that are transifex and need to be part of the language packs
const externalExtensionsWithTranslations = { export const externalExtensionsWithTranslations = {
'vscode-chrome-debug': 'msjsdiag.debugger-for-chrome', 'vscode-chrome-debug': 'msjsdiag.debugger-for-chrome',
'vscode-node-debug': 'ms-vscode.node-debug', 'vscode-node-debug': 'ms-vscode.node-debug',
'vscode-node-debug2': 'ms-vscode.node-debug2' 'vscode-node-debug2': 'ms-vscode.node-debug2'
@@ -71,7 +71,7 @@ interface Map<V> {
interface Item { interface Item {
id: string; id: string;
message: string; message: string;
comment: string; comment?: string;
} }
export interface Resource { export interface Resource {
@@ -137,27 +137,6 @@ module PackageJsonFormat {
} }
} }
interface ModuleJsonFormat {
messages: string[];
keys: (string | LocalizeInfo)[];
}
module ModuleJsonFormat {
export function is(value: any): value is ModuleJsonFormat {
let candidate = value as ModuleJsonFormat;
return Is.defined(candidate)
&& Is.array(candidate.messages) && candidate.messages.every(message => Is.string(message))
&& Is.array(candidate.keys) && candidate.keys.every(key => Is.string(key) || LocalizeInfo.is(key));
}
}
interface BundledExtensionHeaderFormat {
id: string;
type: string;
hash: string;
outDir: string;
}
interface BundledExtensionFormat { interface BundledExtensionFormat {
[key: string]: { [key: string]: {
messages: string[]; messages: string[];
@@ -168,7 +147,7 @@ interface BundledExtensionFormat {
export class Line { export class Line {
private buffer: string[] = []; private buffer: string[] = [];
constructor(private indent: number = 0) { constructor(indent: number = 0) {
if (indent > 0) { if (indent > 0) {
this.buffer.push(new Array(indent + 1).join(' ')); this.buffer.push(new Array(indent + 1).join(' '));
} }
@@ -235,8 +214,8 @@ export class XLF {
let existingKeys = new Set<string>(); let existingKeys = new Set<string>();
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
let key = keys[i]; let key = keys[i];
let realKey: string; let realKey: string | undefined;
let comment: string; let comment: string | undefined;
if (Is.string(key)) { if (Is.string(key)) {
realKey = key; realKey = key;
comment = undefined; comment = undefined;
@@ -286,17 +265,17 @@ export class XLF {
} }
static parsePseudo = function (xlfString: string): Promise<ParsedXLF[]> { static parsePseudo = function (xlfString: string): Promise<ParsedXLF[]> {
return new Promise((resolve, reject) => { return new Promise((resolve) => {
let parser = new xml2js.Parser(); let parser = new xml2js.Parser();
let files: { messages: Map<string>, originalFilePath: string, language: string }[] = []; let files: { messages: Map<string>, originalFilePath: string, language: string }[] = [];
parser.parseString(xlfString, function (err, result) { parser.parseString(xlfString, function (_err: any, result: any) {
const fileNodes: any[] = result['xliff']['file']; const fileNodes: any[] = result['xliff']['file'];
fileNodes.forEach(file => { fileNodes.forEach(file => {
const originalFilePath = file.$.original; const originalFilePath = file.$.original;
const messages: Map<string> = {}; const messages: Map<string> = {};
const transUnits = file.body[0]['trans-unit']; const transUnits = file.body[0]['trans-unit'];
if (transUnits) { if (transUnits) {
transUnits.forEach(unit => { transUnits.forEach((unit: any) => {
const key = unit.$.id; const key = unit.$.id;
const val = pseudify(unit.source[0]['_'].toString()); const val = pseudify(unit.source[0]['_'].toString());
if (key && val) { if (key && val) {
@@ -317,7 +296,7 @@ export class XLF {
let files: { messages: Map<string>, originalFilePath: string, language: string }[] = []; let files: { messages: Map<string>, originalFilePath: string, language: string }[] = [];
parser.parseString(xlfString, function (err, result) { parser.parseString(xlfString, function (err: any, result: any) {
if (err) { if (err) {
reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`)); reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`));
} }
@@ -340,17 +319,20 @@ export class XLF {
const transUnits = file.body[0]['trans-unit']; const transUnits = file.body[0]['trans-unit'];
if (transUnits) { if (transUnits) {
transUnits.forEach(unit => { transUnits.forEach((unit: any) => {
const key = unit.$.id; const key = unit.$.id;
if (!unit.target) { if (!unit.target) {
return; // No translation available return; // No translation available
} }
const val = unit.target.toString(); let val = unit.target[0];
if (typeof val !== 'string') {
val = val._;
}
if (key && val) { if (key && val) {
messages[key] = decodeEntities(val); messages[key] = decodeEntities(val);
} else { } else {
reject(new Error(`XLF parsing error: XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.`)); reject(new Error(`XLF parsing error: XLIFF file ${originalFilePath} does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.`));
} }
}); });
files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() }); files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() });
@@ -369,7 +351,7 @@ export interface ITask<T> {
interface ILimitedTaskFactory<T> { interface ILimitedTaskFactory<T> {
factory: ITask<Promise<T>>; factory: ITask<Promise<T>>;
c: (value?: T | Thenable<T>) => void; c: (value?: T | Promise<T>) => void;
e: (error?: any) => void; e: (error?: any) => void;
} }
@@ -391,7 +373,7 @@ export class Limiter<T> {
private consume(): void { private consume(): void {
while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) {
const iLimitedTask = this.outstandingPromises.shift(); const iLimitedTask = this.outstandingPromises.shift()!;
this.runningPromises++; this.runningPromises++;
const promise = iLimitedTask.factory(); const promise = iLimitedTask.factory();
@@ -419,8 +401,8 @@ function stripComments(content: string): string {
* Third matches block comments * Third matches block comments
* Fourth matches line comments * Fourth matches line comments
*/ */
var regexp: RegExp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; const regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
let result = content.replace(regexp, (match, m1, m2, m3, m4) => { let result = content.replace(regexp, (match, _m1, _m2, m3, m4) => {
// Only one of m1, m2, m3, m4 matches // Only one of m1, m2, m3, m4 matches
if (m3) { if (m3) {
// A block comment. Replace with nothing // A block comment. Replace with nothing
@@ -442,9 +424,9 @@ function stripComments(content: string): string {
} }
function escapeCharacters(value: string): string { function escapeCharacters(value: string): string {
var result: string[] = []; const result: string[] = [];
for (var i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
var ch = value.charAt(i); const ch = value.charAt(i);
switch (ch) { switch (ch) {
case '\'': case '\'':
result.push('\\\''); result.push('\\\'');
@@ -484,7 +466,6 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
let statistics: Map<number> = Object.create(null); let statistics: Map<number> = Object.create(null);
let total: number = 0;
let defaultMessages: Map<Map<string>> = Object.create(null); let defaultMessages: Map<Map<string>> = Object.create(null);
let modules = Object.keys(keysSection); let modules = Object.keys(keysSection);
modules.forEach((module) => { modules.forEach((module) => {
@@ -497,7 +478,6 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
let messageMap: Map<string> = Object.create(null); let messageMap: Map<string> = Object.create(null);
defaultMessages[module] = messageMap; defaultMessages[module] = messageMap;
keys.map((key, i) => { keys.map((key, i) => {
total++;
if (typeof key === 'string') { if (typeof key === 'string') {
messageMap[key] = messages[i]; messageMap[key] = messages[i];
} else { } else {
@@ -520,7 +500,7 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
modules.forEach((module) => { modules.forEach((module) => {
let order = keysSection[module]; let order = keysSection[module];
let i18nFile = path.join(cwd, module) + '.i18n.json'; let i18nFile = path.join(cwd, module) + '.i18n.json';
let messages: Map<string> = null; let messages: Map<string> | null = null;
if (fs.existsSync(i18nFile)) { if (fs.existsSync(i18nFile)) {
let content = stripComments(fs.readFileSync(i18nFile, 'utf8')); let content = stripComments(fs.readFileSync(i18nFile, 'utf8'));
messages = JSON.parse(content); messages = JSON.parse(content);
@@ -533,13 +513,13 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json
} }
let localizedMessages: string[] = []; let localizedMessages: string[] = [];
order.forEach((keyInfo) => { order.forEach((keyInfo) => {
let key: string = null; let key: string | null = null;
if (typeof keyInfo === 'string') { if (typeof keyInfo === 'string') {
key = keyInfo; key = keyInfo;
} else { } else {
key = keyInfo.key; key = keyInfo.key;
} }
let message: string = messages[key]; let message: string = messages![key];
if (!message) { if (!message) {
if (process.env['VSCODE_BUILD_VERBOSE']) { if (process.env['VSCODE_BUILD_VERBOSE']) {
log(`No localized message found for key ${key} in module ${module}. Using default message.`); log(`No localized message found for key ${key} in module ${module}. Using default message.`);
@@ -824,8 +804,8 @@ export function createXlfFilesForIsl(): ThroughStream {
} }
export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream { export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream {
let tryGetPromises = []; let tryGetPromises: Array<Promise<boolean>> = [];
let updateCreatePromises = []; let updateCreatePromises: Array<Promise<boolean>> = [];
return through(function (this: ThroughStream, file: File) { return through(function (this: ThroughStream, file: File) {
const project = path.dirname(file.relative); const project = path.dirname(file.relative);
@@ -890,7 +870,7 @@ function getAllResources(project: string, apiHostname: string, username: string,
export function findObsoleteResources(apiHostname: string, username: string, password: string): ThroughStream { export function findObsoleteResources(apiHostname: string, username: string, password: string): ThroughStream {
let resourcesByProject: Map<string[]> = Object.create(null); let resourcesByProject: Map<string[]> = Object.create(null);
resourcesByProject[extensionsProject] = [].concat(externalExtensionsWithTranslations); // clone resourcesByProject[extensionsProject] = ([] as any[]).concat(externalExtensionsWithTranslations); // clone
return through(function (this: ThroughStream, file: File) { return through(function (this: ThroughStream, file: File) {
const project = path.dirname(file.relative); const project = path.dirname(file.relative);
@@ -907,7 +887,7 @@ export function findObsoleteResources(apiHostname: string, username: string, pas
const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8')); const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'));
let i18Resources = [...json.editor, ...json.workbench].map((r: Resource) => r.project + '/' + r.name.replace(/\//g, '_')); let i18Resources = [...json.editor, ...json.workbench].map((r: Resource) => r.project + '/' + r.name.replace(/\//g, '_'));
let extractedResources = []; let extractedResources: string[] = [];
for (let project of [workbenchProject, editorProject]) { for (let project of [workbenchProject, editorProject]) {
for (let resource of resourcesByProject[project]) { for (let resource of resourcesByProject[project]) {
if (resource !== 'setup_messages') { if (resource !== 'setup_messages') {
@@ -920,7 +900,7 @@ export function findObsoleteResources(apiHostname: string, username: string, pas
console.log(`[i18n] Missing resources in file 'build/lib/i18n.resources.json': JSON.stringify(${extractedResources.filter(p => i18Resources.indexOf(p) === -1)})`); console.log(`[i18n] Missing resources in file 'build/lib/i18n.resources.json': JSON.stringify(${extractedResources.filter(p => i18Resources.indexOf(p) === -1)})`);
} }
let promises = []; let promises: Array<Promise<void>> = [];
for (let project in resourcesByProject) { for (let project in resourcesByProject) {
promises.push( promises.push(
getAllResources(project, apiHostname, username, password).then(resources => { getAllResources(project, apiHostname, username, password).then(resources => {
@@ -965,7 +945,7 @@ function tryGetResource(project: string, slug: string, apiHostname: string, cred
} }
function createResource(project: string, slug: string, xlfFile: File, apiHostname: string, credentials: any): Promise<any> { function createResource(project: string, slug: string, xlfFile: File, apiHostname: string, credentials: any): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((_resolve, reject) => {
const data = JSON.stringify({ const data = JSON.stringify({
'content': xlfFile.contents.toString(), 'content': xlfFile.contents.toString(),
'name': slug, 'name': slug,
@@ -1056,8 +1036,8 @@ export function pullCoreAndExtensionsXlfFiles(apiHostname: string, username: str
// extensions // extensions
let extensionsToLocalize = Object.create(null); let extensionsToLocalize = Object.create(null);
glob.sync('./extensions/**/*.nls.json', ).forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true); glob.sync('./extensions/**/*.nls.json').forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true);
glob.sync('./extensions/*/node_modules/vscode-nls', ).forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true); glob.sync('./extensions/*/node_modules/vscode-nls').forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true);
Object.keys(extensionsToLocalize).forEach(extension => { Object.keys(extensionsToLocalize).forEach(extension => {
_coreAndExtensionResources.push({ name: extension, project: extensionsProject }); _coreAndExtensionResources.push({ name: extension, project: extensionsProject });
@@ -1085,7 +1065,7 @@ function pullXlfFiles(apiHostname: string, username: string, password: string, l
let expectedTranslationsCount = resources.length; let expectedTranslationsCount = resources.length;
let translationsRetrieved = 0, called = false; let translationsRetrieved = 0, called = false;
return readable(function (count, callback) { return readable(function (_count: any, callback: any) {
// Mark end of stream when all resources were retrieved // Mark end of stream when all resources were retrieved
if (translationsRetrieved === expectedTranslationsCount) { if (translationsRetrieved === expectedTranslationsCount) {
return this.emit('end'); return this.emit('end');
@@ -1095,7 +1075,7 @@ function pullXlfFiles(apiHostname: string, username: string, password: string, l
called = true; called = true;
const stream = this; const stream = this;
resources.map(function (resource) { resources.map(function (resource) {
retrieveResource(language, resource, apiHostname, credentials).then((file: File) => { retrieveResource(language, resource, apiHostname, credentials).then((file: File | null) => {
if (file) { if (file) {
stream.emit('data', file); stream.emit('data', file);
} }
@@ -1107,10 +1087,10 @@ function pullXlfFiles(apiHostname: string, username: string, password: string, l
callback(); callback();
}); });
} }
const limiter = new Limiter<File>(NUMBER_OF_CONCURRENT_DOWNLOADS); const limiter = new Limiter<File | null>(NUMBER_OF_CONCURRENT_DOWNLOADS);
function retrieveResource(language: Language, resource: Resource, apiHostname, credentials): Promise<File> { function retrieveResource(language: Language, resource: Resource, apiHostname: string, credentials: string): Promise<File | null> {
return limiter.queue(() => new Promise<File>((resolve, reject) => { return limiter.queue(() => new Promise<File | null>((resolve, reject) => {
const slug = resource.name.replace(/\//g, '_'); const slug = resource.name.replace(/\//g, '_');
const project = resource.project; const project = resource.project;
let transifexLanguageId = language.id === 'ps' ? 'en' : language.transifexId || language.id; let transifexLanguageId = language.id === 'ps' ? 'en' : language.transifexId || language.id;
@@ -1212,10 +1192,10 @@ export function prepareI18nPackFiles(externalExtensions: Map<string>, resultingT
let parsePromises: Promise<ParsedXLF[]>[] = []; let parsePromises: Promise<ParsedXLF[]>[] = [];
let mainPack: I18nPack = { version: i18nPackVersion, contents: {} }; let mainPack: I18nPack = { version: i18nPackVersion, contents: {} };
let extensionsPacks: Map<I18nPack> = {}; let extensionsPacks: Map<I18nPack> = {};
let errors: any[] = [];
return through(function (this: ThroughStream, xlf: File) { return through(function (this: ThroughStream, xlf: File) {
let stream = this; let project = path.dirname(xlf.relative);
let project = path.dirname(xlf.path); let resource = path.basename(xlf.relative, '.xlf');
let resource = path.basename(xlf.path, '.xlf');
let contents = xlf.contents.toString(); let contents = xlf.contents.toString();
let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents); let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents);
parsePromises.push(parsePromise); parsePromises.push(parsePromise);
@@ -1242,10 +1222,15 @@ export function prepareI18nPackFiles(externalExtensions: Map<string>, resultingT
} }
}); });
} }
); ).catch(reason => {
errors.push(reason);
});
}, function () { }, function () {
Promise.all(parsePromises) Promise.all(parsePromises)
.then(() => { .then(() => {
if (errors.length > 0) {
throw errors;
}
const translatedMainFile = createI18nFile('./main', mainPack); const translatedMainFile = createI18nFile('./main', mainPack);
resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' }); resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' });
@@ -1264,7 +1249,9 @@ export function prepareI18nPackFiles(externalExtensions: Map<string>, resultingT
} }
this.queue(null); this.queue(null);
}) })
.catch(reason => { throw new Error(reason); }); .catch((reason) => {
this.emit('error', reason);
});
}); });
} }
@@ -1285,11 +1272,15 @@ export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup):
stream.queue(translatedFile); stream.queue(translatedFile);
}); });
} }
); ).catch(reason => {
this.emit('error', reason);
});
}, function () { }, function () {
Promise.all(parsePromises) Promise.all(parsePromises)
.then(() => { this.queue(null); }) .then(() => { this.queue(null); })
.catch(reason => { throw new Error(reason); }); .catch(reason => {
this.emit('error', reason);
});
}); });
} }
@@ -1306,7 +1297,7 @@ function createIslFile(originalFilePath: string, messages: Map<string>, language
let firstChar = line.charAt(0); let firstChar = line.charAt(0);
if (firstChar === '[' || firstChar === ';') { if (firstChar === '[' || firstChar === ';') {
if (line === '; *** Inno Setup version 5.5.3+ English messages ***') { if (line === '; *** Inno Setup version 5.5.3+ English messages ***') {
content.push(`; *** Inno Setup version 5.5.3+ ${innoSetup.defaultInfo.name} messages ***`); content.push(`; *** Inno Setup version 5.5.3+ ${innoSetup.defaultInfo!.name} messages ***`);
} else { } else {
content.push(line); content.push(line);
} }
@@ -1316,9 +1307,9 @@ function createIslFile(originalFilePath: string, messages: Map<string>, language
let translated = line; let translated = line;
if (key) { if (key) {
if (key === 'LanguageName') { if (key === 'LanguageName') {
translated = `${key}=${innoSetup.defaultInfo.name}`; translated = `${key}=${innoSetup.defaultInfo!.name}`;
} else if (key === 'LanguageID') { } else if (key === 'LanguageID') {
translated = `${key}=${innoSetup.defaultInfo.id}`; translated = `${key}=${innoSetup.defaultInfo!.id}`;
} else if (key === 'LanguageCodePage') { } else if (key === 'LanguageCodePage') {
translated = `${key}=${innoSetup.codePage.substr(2)}`; translated = `${key}=${innoSetup.codePage.substr(2)}`;
} else { } else {
@@ -1339,14 +1330,14 @@ function createIslFile(originalFilePath: string, messages: Map<string>, language
return new File({ return new File({
path: filePath, path: filePath,
contents: iconv.encode(Buffer.from(content.join('\r\n'), 'utf8'), innoSetup.codePage) contents: iconv.encode(Buffer.from(content.join('\r\n'), 'utf8').toString(), innoSetup.codePage)
}); });
} }
function encodeEntities(value: string): string { function encodeEntities(value: string): string {
var result: string[] = []; let result: string[] = [];
for (var i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
var ch = value[i]; let ch = value[i];
switch (ch) { switch (ch) {
case '<': case '<':
result.push('&lt;'); result.push('&lt;');

View File

@@ -3,13 +3,12 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var ts = require("typescript"); const ts = require("typescript");
var lazy = require("lazy.js"); const lazy = require("lazy.js");
var event_stream_1 = require("event-stream"); const event_stream_1 = require("event-stream");
var File = require("vinyl"); const File = require("vinyl");
var sm = require("source-map"); const sm = require("source-map");
var assign = require("object-assign"); const path = require("path");
var path = require("path");
var CollectStepResult; var CollectStepResult;
(function (CollectStepResult) { (function (CollectStepResult) {
CollectStepResult[CollectStepResult["Yes"] = 0] = "Yes"; CollectStepResult[CollectStepResult["Yes"] = 0] = "Yes";
@@ -18,9 +17,9 @@ var CollectStepResult;
CollectStepResult[CollectStepResult["NoAndRecurse"] = 3] = "NoAndRecurse"; CollectStepResult[CollectStepResult["NoAndRecurse"] = 3] = "NoAndRecurse";
})(CollectStepResult || (CollectStepResult = {})); })(CollectStepResult || (CollectStepResult = {}));
function collect(node, fn) { function collect(node, fn) {
var result = []; const result = [];
function loop(node) { function loop(node) {
var stepResult = fn(node); const stepResult = fn(node);
if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) { if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) {
result.push(node); result.push(node);
} }
@@ -32,43 +31,45 @@ function collect(node, fn) {
return result; return result;
} }
function clone(object) { function clone(object) {
var result = {}; const result = {};
for (var id in object) { for (const id in object) {
result[id] = object[id]; result[id] = object[id];
} }
return result; return result;
} }
function template(lines) { function template(lines) {
var indent = '', wrap = ''; let indent = '', wrap = '';
if (lines.length > 1) { if (lines.length > 1) {
indent = '\t'; indent = '\t';
wrap = '\n'; wrap = '\n';
} }
return "/*---------------------------------------------------------\n * Copyright (C) Microsoft Corporation. All rights reserved.\n *--------------------------------------------------------*/\ndefine([], [" + (wrap + lines.map(function (l) { return indent + l; }).join(',\n') + wrap) + "]);"; return `/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
define([], [${wrap + lines.map(l => indent + l).join(',\n') + wrap}]);`;
} }
/** /**
* Returns a stream containing the patched JavaScript and source maps. * Returns a stream containing the patched JavaScript and source maps.
*/ */
function nls() { function nls() {
var input = event_stream_1.through(); const input = event_stream_1.through();
var output = input.pipe(event_stream_1.through(function (f) { const output = input.pipe(event_stream_1.through(function (f) {
var _this = this;
if (!f.sourceMap) { if (!f.sourceMap) {
return this.emit('error', new Error("File " + f.relative + " does not have sourcemaps.")); return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`));
} }
var source = f.sourceMap.sources[0]; let source = f.sourceMap.sources[0];
if (!source) { if (!source) {
return this.emit('error', new Error("File " + f.relative + " does not have a source in the source map.")); return this.emit('error', new Error(`File ${f.relative} does not have a source in the source map.`));
} }
var root = f.sourceMap.sourceRoot; const root = f.sourceMap.sourceRoot;
if (root) { if (root) {
source = path.join(root, source); source = path.join(root, source);
} }
var typescript = f.sourceMap.sourcesContent[0]; const typescript = f.sourceMap.sourcesContent[0];
if (!typescript) { if (!typescript) {
return this.emit('error', new Error("File " + f.relative + " does not have the original content in the source map.")); return this.emit('error', new Error(`File ${f.relative} does not have the original content in the source map.`));
} }
nls.patchFiles(f, typescript).forEach(function (f) { return _this.emit('data', f); }); nls.patchFiles(f, typescript).forEach(f => this.emit('data', f));
})); }));
return event_stream_1.duplex(input, output); return event_stream_1.duplex(input, output);
} }
@@ -76,8 +77,7 @@ function isImportNode(node) {
return node.kind === ts.SyntaxKind.ImportDeclaration || node.kind === ts.SyntaxKind.ImportEqualsDeclaration; return node.kind === ts.SyntaxKind.ImportDeclaration || node.kind === ts.SyntaxKind.ImportEqualsDeclaration;
} }
(function (nls_1) { (function (nls_1) {
function fileFrom(file, contents, path) { function fileFrom(file, contents, path = file.path) {
if (path === void 0) { path = file.path; }
return new File({ return new File({
contents: Buffer.from(contents), contents: Buffer.from(contents),
base: file.base, base: file.base,
@@ -87,29 +87,27 @@ function isImportNode(node) {
} }
nls_1.fileFrom = fileFrom; nls_1.fileFrom = fileFrom;
function mappedPositionFrom(source, lc) { function mappedPositionFrom(source, lc) {
return { source: source, line: lc.line + 1, column: lc.character }; return { source, line: lc.line + 1, column: lc.character };
} }
nls_1.mappedPositionFrom = mappedPositionFrom; nls_1.mappedPositionFrom = mappedPositionFrom;
function lcFrom(position) { function lcFrom(position) {
return { line: position.line - 1, character: position.column }; return { line: position.line - 1, character: position.column };
} }
nls_1.lcFrom = lcFrom; nls_1.lcFrom = lcFrom;
var SingleFileServiceHost = /** @class */ (function () { class SingleFileServiceHost {
function SingleFileServiceHost(options, filename, contents) { constructor(options, filename, contents) {
var _this = this;
this.options = options; this.options = options;
this.filename = filename; this.filename = filename;
this.getCompilationSettings = function () { return _this.options; }; this.getCompilationSettings = () => this.options;
this.getScriptFileNames = function () { return [_this.filename]; }; this.getScriptFileNames = () => [this.filename];
this.getScriptVersion = function () { return '1'; }; this.getScriptVersion = () => '1';
this.getScriptSnapshot = function (name) { return name === _this.filename ? _this.file : _this.lib; }; this.getScriptSnapshot = (name) => name === this.filename ? this.file : this.lib;
this.getCurrentDirectory = function () { return ''; }; this.getCurrentDirectory = () => '';
this.getDefaultLibFileName = function () { return 'lib.d.ts'; }; this.getDefaultLibFileName = () => 'lib.d.ts';
this.file = ts.ScriptSnapshot.fromString(contents); this.file = ts.ScriptSnapshot.fromString(contents);
this.lib = ts.ScriptSnapshot.fromString(''); this.lib = ts.ScriptSnapshot.fromString('');
} }
return SingleFileServiceHost; }
}());
nls_1.SingleFileServiceHost = SingleFileServiceHost; nls_1.SingleFileServiceHost = SingleFileServiceHost;
function isCallExpressionWithinTextSpanCollectStep(textSpan, node) { function isCallExpressionWithinTextSpanCollectStep(textSpan, node) {
if (!ts.textSpanContainsTextSpan({ start: node.pos, length: node.end - node.pos }, textSpan)) { if (!ts.textSpanContainsTextSpan({ start: node.pos, length: node.end - node.pos }, textSpan)) {
@@ -117,97 +115,96 @@ function isImportNode(node) {
} }
return node.kind === ts.SyntaxKind.CallExpression ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse; return node.kind === ts.SyntaxKind.CallExpression ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse;
} }
function analyze(contents, options) { function analyze(contents, options = {}) {
if (options === void 0) { options = {}; } const filename = 'file.ts';
var filename = 'file.ts'; const serviceHost = new SingleFileServiceHost(Object.assign(clone(options), { noResolve: true }), filename, contents);
var serviceHost = new SingleFileServiceHost(assign(clone(options), { noResolve: true }), filename, contents); const service = ts.createLanguageService(serviceHost);
var service = ts.createLanguageService(serviceHost); const sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true);
var sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true);
// all imports // all imports
var imports = lazy(collect(sourceFile, function (n) { return isImportNode(n) ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse; })); const imports = lazy(collect(sourceFile, n => isImportNode(n) ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse));
// import nls = require('vs/nls'); // import nls = require('vs/nls');
var importEqualsDeclarations = imports const importEqualsDeclarations = imports
.filter(function (n) { return n.kind === ts.SyntaxKind.ImportEqualsDeclaration; }) .filter(n => n.kind === ts.SyntaxKind.ImportEqualsDeclaration)
.map(function (n) { return n; }) .map(n => n)
.filter(function (d) { return d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference; }) .filter(d => d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference)
.filter(function (d) { return d.moduleReference.expression.getText() === '\'vs/nls\''; }); .filter(d => d.moduleReference.expression.getText() === '\'vs/nls\'');
// import ... from 'vs/nls'; // import ... from 'vs/nls';
var importDeclarations = imports const importDeclarations = imports
.filter(function (n) { return n.kind === ts.SyntaxKind.ImportDeclaration; }) .filter(n => n.kind === ts.SyntaxKind.ImportDeclaration)
.map(function (n) { return n; }) .map(n => n)
.filter(function (d) { return d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral; }) .filter(d => d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral)
.filter(function (d) { return d.moduleSpecifier.getText() === '\'vs/nls\''; }) .filter(d => d.moduleSpecifier.getText() === '\'vs/nls\'')
.filter(function (d) { return !!d.importClause && !!d.importClause.namedBindings; }); .filter(d => !!d.importClause && !!d.importClause.namedBindings);
var nlsExpressions = importEqualsDeclarations const nlsExpressions = importEqualsDeclarations
.map(function (d) { return d.moduleReference.expression; }) .map(d => d.moduleReference.expression)
.concat(importDeclarations.map(function (d) { return d.moduleSpecifier; })) .concat(importDeclarations.map(d => d.moduleSpecifier))
.map(function (d) { return ({ .map(d => ({
start: ts.getLineAndCharacterOfPosition(sourceFile, d.getStart()), start: ts.getLineAndCharacterOfPosition(sourceFile, d.getStart()),
end: ts.getLineAndCharacterOfPosition(sourceFile, d.getEnd()) end: ts.getLineAndCharacterOfPosition(sourceFile, d.getEnd())
}); }); }));
// `nls.localize(...)` calls // `nls.localize(...)` calls
var nlsLocalizeCallExpressions = importDeclarations const nlsLocalizeCallExpressions = importDeclarations
.filter(function (d) { return d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport; }) .filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport))
.map(function (d) { return d.importClause.namedBindings.name; }) .map(d => d.importClause.namedBindings.name)
.concat(importEqualsDeclarations.map(function (d) { return d.name; })) .concat(importEqualsDeclarations.map(d => d.name))
// find read-only references to `nls` // find read-only references to `nls`
.map(function (n) { return service.getReferencesAtPosition(filename, n.pos + 1); }) .map(n => service.getReferencesAtPosition(filename, n.pos + 1))
.flatten() .flatten()
.filter(function (r) { return !r.isWriteAccess; }) .filter(r => !r.isWriteAccess)
// find the deepest call expressions AST nodes that contain those references // find the deepest call expressions AST nodes that contain those references
.map(function (r) { return collect(sourceFile, function (n) { return isCallExpressionWithinTextSpanCollectStep(r.textSpan, n); }); }) .map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n)))
.map(function (a) { return lazy(a).last(); }) .map(a => lazy(a).last())
.filter(function (n) { return !!n; }) .filter(n => !!n)
.map(function (n) { return n; }) .map(n => n)
// only `localize` calls // only `localize` calls
.filter(function (n) { return n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize'; }); .filter(n => n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize');
// `localize` named imports // `localize` named imports
var allLocalizeImportDeclarations = importDeclarations const allLocalizeImportDeclarations = importDeclarations
.filter(function (d) { return d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports; }) .filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports))
.map(function (d) { return [].concat(d.importClause.namedBindings.elements); }) .map(d => [].concat(d.importClause.namedBindings.elements))
.flatten(); .flatten();
// `localize` read-only references // `localize` read-only references
var localizeReferences = allLocalizeImportDeclarations const localizeReferences = allLocalizeImportDeclarations
.filter(function (d) { return d.name.getText() === 'localize'; }) .filter(d => d.name.getText() === 'localize')
.map(function (n) { return service.getReferencesAtPosition(filename, n.pos + 1); }) .map(n => service.getReferencesAtPosition(filename, n.pos + 1))
.flatten() .flatten()
.filter(function (r) { return !r.isWriteAccess; }); .filter(r => !r.isWriteAccess);
// custom named `localize` read-only references // custom named `localize` read-only references
var namedLocalizeReferences = allLocalizeImportDeclarations const namedLocalizeReferences = allLocalizeImportDeclarations
.filter(function (d) { return d.propertyName && d.propertyName.getText() === 'localize'; }) .filter(d => d.propertyName && d.propertyName.getText() === 'localize')
.map(function (n) { return service.getReferencesAtPosition(filename, n.name.pos + 1); }) .map(n => service.getReferencesAtPosition(filename, n.name.pos + 1))
.flatten() .flatten()
.filter(function (r) { return !r.isWriteAccess; }); .filter(r => !r.isWriteAccess);
// find the deepest call expressions AST nodes that contain those references // find the deepest call expressions AST nodes that contain those references
var localizeCallExpressions = localizeReferences const localizeCallExpressions = localizeReferences
.concat(namedLocalizeReferences) .concat(namedLocalizeReferences)
.map(function (r) { return collect(sourceFile, function (n) { return isCallExpressionWithinTextSpanCollectStep(r.textSpan, n); }); }) .map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n)))
.map(function (a) { return lazy(a).last(); }) .map(a => lazy(a).last())
.filter(function (n) { return !!n; }) .filter(n => !!n)
.map(function (n) { return n; }); .map(n => n);
// collect everything // collect everything
var localizeCalls = nlsLocalizeCallExpressions const localizeCalls = nlsLocalizeCallExpressions
.concat(localizeCallExpressions) .concat(localizeCallExpressions)
.map(function (e) { return e.arguments; }) .map(e => e.arguments)
.filter(function (a) { return a.length > 1; }) .filter(a => a.length > 1)
.sort(function (a, b) { return a[0].getStart() - b[0].getStart(); }) .sort((a, b) => a[0].getStart() - b[0].getStart())
.map(function (a) { return ({ .map(a => ({
keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) }, keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) },
key: a[0].getText(), key: a[0].getText(),
valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) }, valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) },
value: a[1].getText() value: a[1].getText()
}); }); }));
return { return {
localizeCalls: localizeCalls.toArray(), localizeCalls: localizeCalls.toArray(),
nlsExpressions: nlsExpressions.toArray() nlsExpressions: nlsExpressions.toArray()
}; };
} }
nls_1.analyze = analyze; nls_1.analyze = analyze;
var TextModel = /** @class */ (function () { class TextModel {
function TextModel(contents) { constructor(contents) {
var regex = /\r\n|\r|\n/g; const regex = /\r\n|\r|\n/g;
var index = 0; let index = 0;
var match; let match;
this.lines = []; this.lines = [];
this.lineEndings = []; this.lineEndings = [];
while (match = regex.exec(contents)) { while (match = regex.exec(contents)) {
@@ -220,85 +217,80 @@ function isImportNode(node) {
this.lineEndings.push(''); this.lineEndings.push('');
} }
} }
TextModel.prototype.get = function (index) { get(index) {
return this.lines[index]; return this.lines[index];
}; }
TextModel.prototype.set = function (index, line) { set(index, line) {
this.lines[index] = line; this.lines[index] = line;
}; }
Object.defineProperty(TextModel.prototype, "lineCount", { get lineCount() {
get: function () { return this.lines.length;
return this.lines.length; }
},
enumerable: true,
configurable: true
});
/** /**
* Applies patch(es) to the model. * Applies patch(es) to the model.
* Multiple patches must be ordered. * Multiple patches must be ordered.
* Does not support patches spanning multiple lines. * Does not support patches spanning multiple lines.
*/ */
TextModel.prototype.apply = function (patch) { apply(patch) {
var startLineNumber = patch.span.start.line; const startLineNumber = patch.span.start.line;
var endLineNumber = patch.span.end.line; const endLineNumber = patch.span.end.line;
var startLine = this.lines[startLineNumber] || ''; const startLine = this.lines[startLineNumber] || '';
var endLine = this.lines[endLineNumber] || ''; const endLine = this.lines[endLineNumber] || '';
this.lines[startLineNumber] = [ this.lines[startLineNumber] = [
startLine.substring(0, patch.span.start.character), startLine.substring(0, patch.span.start.character),
patch.content, patch.content,
endLine.substring(patch.span.end.character) endLine.substring(patch.span.end.character)
].join(''); ].join('');
for (var i = startLineNumber + 1; i <= endLineNumber; i++) { for (let i = startLineNumber + 1; i <= endLineNumber; i++) {
this.lines[i] = ''; this.lines[i] = '';
} }
}; }
TextModel.prototype.toString = function () { toString() {
return lazy(this.lines).zip(this.lineEndings) return lazy(this.lines).zip(this.lineEndings)
.flatten().toArray().join(''); .flatten().toArray().join('');
}; }
return TextModel; }
}());
nls_1.TextModel = TextModel; nls_1.TextModel = TextModel;
function patchJavascript(patches, contents, moduleId) { function patchJavascript(patches, contents, moduleId) {
var model = new nls.TextModel(contents); const model = new nls.TextModel(contents);
// patch the localize calls // patch the localize calls
lazy(patches).reverse().each(function (p) { return model.apply(p); }); lazy(patches).reverse().each(p => model.apply(p));
// patch the 'vs/nls' imports // patch the 'vs/nls' imports
var firstLine = model.get(0); const firstLine = model.get(0);
var patchedFirstLine = firstLine.replace(/(['"])vs\/nls\1/g, "$1vs/nls!" + moduleId + "$1"); const patchedFirstLine = firstLine.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`);
model.set(0, patchedFirstLine); model.set(0, patchedFirstLine);
return model.toString(); return model.toString();
} }
nls_1.patchJavascript = patchJavascript; nls_1.patchJavascript = patchJavascript;
function patchSourcemap(patches, rsm, smc) { function patchSourcemap(patches, rsm, smc) {
var smg = new sm.SourceMapGenerator({ const smg = new sm.SourceMapGenerator({
file: rsm.file, file: rsm.file,
sourceRoot: rsm.sourceRoot sourceRoot: rsm.sourceRoot
}); });
patches = patches.reverse(); patches = patches.reverse();
var currentLine = -1; let currentLine = -1;
var currentLineDiff = 0; let currentLineDiff = 0;
var source = null; let source = null;
smc.eachMapping(function (m) { smc.eachMapping(m => {
var patch = patches[patches.length - 1]; const patch = patches[patches.length - 1];
var original = { line: m.originalLine, column: m.originalColumn }; const original = { line: m.originalLine, column: m.originalColumn };
var generated = { line: m.generatedLine, column: m.generatedColumn }; const generated = { line: m.generatedLine, column: m.generatedColumn };
if (currentLine !== generated.line) { if (currentLine !== generated.line) {
currentLineDiff = 0; currentLineDiff = 0;
} }
currentLine = generated.line; currentLine = generated.line;
generated.column += currentLineDiff; generated.column += currentLineDiff;
if (patch && m.generatedLine - 1 === patch.span.end.line && m.generatedColumn === patch.span.end.character) { if (patch && m.generatedLine - 1 === patch.span.end.line && m.generatedColumn === patch.span.end.character) {
var originalLength = patch.span.end.character - patch.span.start.character; const originalLength = patch.span.end.character - patch.span.start.character;
var modifiedLength = patch.content.length; const modifiedLength = patch.content.length;
var lengthDiff = modifiedLength - originalLength; const lengthDiff = modifiedLength - originalLength;
currentLineDiff += lengthDiff; currentLineDiff += lengthDiff;
generated.column += lengthDiff; generated.column += lengthDiff;
patches.pop(); patches.pop();
} }
source = rsm.sourceRoot ? path.relative(rsm.sourceRoot, m.source) : m.source; source = rsm.sourceRoot ? path.relative(rsm.sourceRoot, m.source) : m.source;
source = source.replace(/\\/g, '/'); source = source.replace(/\\/g, '/');
smg.addMapping({ source: source, name: m.name, original: original, generated: generated }); smg.addMapping({ source, name: m.name, original, generated });
}, null, sm.SourceMapConsumer.GENERATED_ORDER); }, null, sm.SourceMapConsumer.GENERATED_ORDER);
if (source) { if (source) {
smg.setSourceContent(source, smc.sourceContentFor(source)); smg.setSourceContent(source, smc.sourceContentFor(source));
@@ -307,47 +299,47 @@ function isImportNode(node) {
} }
nls_1.patchSourcemap = patchSourcemap; nls_1.patchSourcemap = patchSourcemap;
function patch(moduleId, typescript, javascript, sourcemap) { function patch(moduleId, typescript, javascript, sourcemap) {
var _a = analyze(typescript), localizeCalls = _a.localizeCalls, nlsExpressions = _a.nlsExpressions; const { localizeCalls, nlsExpressions } = analyze(typescript);
if (localizeCalls.length === 0) { if (localizeCalls.length === 0) {
return { javascript: javascript, sourcemap: sourcemap }; return { javascript, sourcemap };
} }
var nlsKeys = template(localizeCalls.map(function (lc) { return lc.key; })); const nlsKeys = template(localizeCalls.map(lc => lc.key));
var nls = template(localizeCalls.map(function (lc) { return lc.value; })); const nls = template(localizeCalls.map(lc => lc.value));
var smc = new sm.SourceMapConsumer(sourcemap); const smc = new sm.SourceMapConsumer(sourcemap);
var positionFrom = mappedPositionFrom.bind(null, sourcemap.sources[0]); const positionFrom = mappedPositionFrom.bind(null, sourcemap.sources[0]);
var i = 0; let i = 0;
// build patches // build patches
var patches = lazy(localizeCalls) const patches = lazy(localizeCalls)
.map(function (lc) { return ([ .map(lc => ([
{ range: lc.keySpan, content: '' + (i++) }, { range: lc.keySpan, content: '' + (i++) },
{ range: lc.valueSpan, content: 'null' } { range: lc.valueSpan, content: 'null' }
]); }) ]))
.flatten() .flatten()
.map(function (c) { .map(c => {
var start = lcFrom(smc.generatedPositionFor(positionFrom(c.range.start))); const start = lcFrom(smc.generatedPositionFor(positionFrom(c.range.start)));
var end = lcFrom(smc.generatedPositionFor(positionFrom(c.range.end))); const end = lcFrom(smc.generatedPositionFor(positionFrom(c.range.end)));
return { span: { start: start, end: end }, content: c.content }; return { span: { start, end }, content: c.content };
}) })
.toArray(); .toArray();
javascript = patchJavascript(patches, javascript, moduleId); javascript = patchJavascript(patches, javascript, moduleId);
// since imports are not within the sourcemap information, // since imports are not within the sourcemap information,
// we must do this MacGyver style // we must do this MacGyver style
if (nlsExpressions.length) { if (nlsExpressions.length) {
javascript = javascript.replace(/^define\(.*$/m, function (line) { javascript = javascript.replace(/^define\(.*$/m, line => {
return line.replace(/(['"])vs\/nls\1/g, "$1vs/nls!" + moduleId + "$1"); return line.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`);
}); });
} }
sourcemap = patchSourcemap(patches, sourcemap, smc); sourcemap = patchSourcemap(patches, sourcemap, smc);
return { javascript: javascript, sourcemap: sourcemap, nlsKeys: nlsKeys, nls: nls }; return { javascript, sourcemap, nlsKeys, nls };
} }
nls_1.patch = patch; nls_1.patch = patch;
function patchFiles(javascriptFile, typescript) { function patchFiles(javascriptFile, typescript) {
// hack? // hack?
var moduleId = javascriptFile.relative const moduleId = javascriptFile.relative
.replace(/\.js$/, '') .replace(/\.js$/, '')
.replace(/\\/g, '/'); .replace(/\\/g, '/');
var _a = patch(moduleId, typescript, javascriptFile.contents.toString(), javascriptFile.sourceMap), javascript = _a.javascript, sourcemap = _a.sourcemap, nlsKeys = _a.nlsKeys, nls = _a.nls; const { javascript, sourcemap, nlsKeys, nls } = patch(moduleId, typescript, javascriptFile.contents.toString(), javascriptFile.sourceMap);
var result = [fileFrom(javascriptFile, javascript)]; const result = [fileFrom(javascriptFile, javascript)];
result[0].sourceMap = sourcemap; result[0].sourceMap = sourcemap;
if (nlsKeys) { if (nlsKeys) {
result.push(fileFrom(javascriptFile, nlsKeys, javascriptFile.path.replace(/\.js$/, '.nls.keys.js'))); result.push(fileFrom(javascriptFile, nlsKeys, javascriptFile.path.replace(/\.js$/, '.nls.keys.js')));

View File

@@ -6,10 +6,9 @@
import * as ts from 'typescript'; import * as ts from 'typescript';
import * as lazy from 'lazy.js'; import * as lazy from 'lazy.js';
import { duplex, through } from 'event-stream'; import { duplex, through } from 'event-stream';
import File = require('vinyl'); import * as File from 'vinyl';
import * as sm from 'source-map'; import * as sm from 'source-map';
import assign = require('object-assign'); import * as path from 'path';
import path = require('path');
declare class FileSourceMap extends File { declare class FileSourceMap extends File {
public sourceMap: sm.RawSourceMap; public sourceMap: sm.RawSourceMap;
@@ -26,7 +25,7 @@ function collect(node: ts.Node, fn: (node: ts.Node) => CollectStepResult): ts.No
const result: ts.Node[] = []; const result: ts.Node[] = [];
function loop(node: ts.Node) { function loop(node: ts.Node) {
var stepResult = fn(node); const stepResult = fn(node);
if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) { if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) {
result.push(node); result.push(node);
@@ -42,8 +41,8 @@ function collect(node: ts.Node, fn: (node: ts.Node) => CollectStepResult): ts.No
} }
function clone<T>(object: T): T { function clone<T>(object: T): T {
var result = <T>{}; const result = <T>{};
for (var id in object) { for (const id in object) {
result[id] = object[id]; result[id] = object[id];
} }
return result; return result;
@@ -67,8 +66,8 @@ define([], [${ wrap + lines.map(l => indent + l).join(',\n') + wrap}]);`;
* Returns a stream containing the patched JavaScript and source maps. * Returns a stream containing the patched JavaScript and source maps.
*/ */
function nls(): NodeJS.ReadWriteStream { function nls(): NodeJS.ReadWriteStream {
var input = through(); const input = through();
var output = input.pipe(through(function (f: FileSourceMap) { const output = input.pipe(through(function (f: FileSourceMap) {
if (!f.sourceMap) { if (!f.sourceMap) {
return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`)); return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`));
} }
@@ -83,7 +82,7 @@ function nls(): NodeJS.ReadWriteStream {
source = path.join(root, source); source = path.join(root, source);
} }
const typescript = f.sourceMap.sourcesContent[0]; const typescript = f.sourceMap.sourcesContent![0];
if (!typescript) { if (!typescript) {
return this.emit('error', new Error(`File ${f.relative} does not have the original content in the source map.`)); return this.emit('error', new Error(`File ${f.relative} does not have the original content in the source map.`));
} }
@@ -174,7 +173,7 @@ module nls {
export function analyze(contents: string, options: ts.CompilerOptions = {}): ILocalizeAnalysisResult { export function analyze(contents: string, options: ts.CompilerOptions = {}): ILocalizeAnalysisResult {
const filename = 'file.ts'; const filename = 'file.ts';
const serviceHost = new SingleFileServiceHost(assign(clone(options), { noResolve: true }), filename, contents); const serviceHost = new SingleFileServiceHost(Object.assign(clone(options), { noResolve: true }), filename, contents);
const service = ts.createLanguageService(serviceHost); const service = ts.createLanguageService(serviceHost);
const sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true); const sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true);
@@ -206,8 +205,8 @@ module nls {
// `nls.localize(...)` calls // `nls.localize(...)` calls
const nlsLocalizeCallExpressions = importDeclarations const nlsLocalizeCallExpressions = importDeclarations
.filter(d => d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) .filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport))
.map(d => (<ts.NamespaceImport>d.importClause.namedBindings).name) .map(d => (<ts.NamespaceImport>d.importClause!.namedBindings).name)
.concat(importEqualsDeclarations.map(d => d.name)) .concat(importEqualsDeclarations.map(d => d.name))
// find read-only references to `nls` // find read-only references to `nls`
@@ -226,8 +225,8 @@ module nls {
// `localize` named imports // `localize` named imports
const allLocalizeImportDeclarations = importDeclarations const allLocalizeImportDeclarations = importDeclarations
.filter(d => d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports) .filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports))
.map(d => [].concat((<ts.NamedImports>d.importClause.namedBindings).elements)) .map(d => ([] as any[]).concat((<ts.NamedImports>d.importClause!.namedBindings!).elements))
.flatten(); .flatten();
// `localize` read-only references // `localize` read-only references
@@ -279,7 +278,7 @@ module nls {
constructor(contents: string) { constructor(contents: string) {
const regex = /\r\n|\r|\n/g; const regex = /\r\n|\r|\n/g;
let index = 0; let index = 0;
let match: RegExpExecArray; let match: RegExpExecArray | null;
this.lines = []; this.lines = [];
this.lineEndings = []; this.lineEndings = [];
@@ -360,7 +359,7 @@ module nls {
patches = patches.reverse(); patches = patches.reverse();
let currentLine = -1; let currentLine = -1;
let currentLineDiff = 0; let currentLineDiff = 0;
let source = null; let source: string | null = null;
smc.eachMapping(m => { smc.eachMapping(m => {
const patch = patches[patches.length - 1]; const patch = patches[patches.length - 1];

View File

@@ -4,29 +4,31 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var path = require("path"); const es = require("event-stream");
var gulp = require("gulp"); const gulp = require("gulp");
var sourcemaps = require("gulp-sourcemaps"); const concat = require("gulp-concat");
var filter = require("gulp-filter"); const minifyCSS = require("gulp-cssnano");
var minifyCSS = require("gulp-cssnano"); const filter = require("gulp-filter");
var uglify = require("gulp-uglify"); const flatmap = require("gulp-flatmap");
var composer = require("gulp-uglify/composer"); const sourcemaps = require("gulp-sourcemaps");
var uglifyes = require("uglify-es"); const uglify = require("gulp-uglify");
var es = require("event-stream"); const composer = require("gulp-uglify/composer");
var concat = require("gulp-concat"); const gulpUtil = require("gulp-util");
var VinylFile = require("vinyl"); const path = require("path");
var bundle = require("./bundle"); const pump = require("pump");
var util = require("./util"); const uglifyes = require("uglify-es");
var gulpUtil = require("gulp-util"); const VinylFile = require("vinyl");
var flatmap = require("gulp-flatmap"); const bundle = require("./bundle");
var pump = require("pump"); const i18n_1 = require("./i18n");
var REPO_ROOT_PATH = path.join(__dirname, '../..'); const stats_1 = require("./stats");
const util = require("./util");
const REPO_ROOT_PATH = path.join(__dirname, '../..');
function log(prefix, message) { function log(prefix, message) {
gulpUtil.log(gulpUtil.colors.cyan('[' + prefix + ']'), message); gulpUtil.log(gulpUtil.colors.cyan('[' + prefix + ']'), message);
} }
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
function loaderConfig(emptyPaths) { function loaderConfig(emptyPaths) {
var result = { const result = {
paths: { paths: {
'vs': 'out-build/vs', 'vs': 'out-build/vs',
'sql': 'out-build/sql', 'sql': 'out-build/sql',
@@ -38,26 +40,26 @@ function loaderConfig(emptyPaths) {
return result; return result;
} }
exports.loaderConfig = loaderConfig; exports.loaderConfig = loaderConfig;
var IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i; const IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i;
function loader(src, bundledFileHeader, bundleLoader) { function loader(src, bundledFileHeader, bundleLoader) {
var sources = [ let sources = [
src + "/vs/loader.js" `${src}/vs/loader.js`
]; ];
if (bundleLoader) { if (bundleLoader) {
sources = sources.concat([ sources = sources.concat([
src + "/vs/css.js", `${src}/vs/css.js`,
src + "/vs/nls.js" `${src}/vs/nls.js`
]); ]);
} }
var isFirst = true; let isFirst = true;
return (gulp return (gulp
.src(sources, { base: "" + src }) .src(sources, { base: `${src}` })
.pipe(es.through(function (data) { .pipe(es.through(function (data) {
if (isFirst) { if (isFirst) {
isFirst = false; isFirst = false;
this.emit('data', new VinylFile({ this.emit('data', new VinylFile({
path: 'fake', path: 'fake',
base: '', base: undefined,
contents: Buffer.from(bundledFileHeader) contents: Buffer.from(bundledFileHeader)
})); }));
this.emit('data', data); this.emit('data', data);
@@ -74,12 +76,12 @@ function loader(src, bundledFileHeader, bundleLoader) {
}))); })));
} }
function toConcatStream(src, bundledFileHeader, sources, dest) { function toConcatStream(src, bundledFileHeader, sources, dest) {
var useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest); const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);
// If a bundle ends up including in any of the sources our copyright, then // If a bundle ends up including in any of the sources our copyright, then
// insert a fake source at the beginning of each bundle with our copyright // insert a fake source at the beginning of each bundle with our copyright
var containsOurCopyright = false; let containsOurCopyright = false;
for (var i = 0, len = sources.length; i < len; i++) { for (let i = 0, len = sources.length; i < len; i++) {
var fileContents = sources[i].contents; const fileContents = sources[i].contents;
if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) { if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) {
containsOurCopyright = true; containsOurCopyright = true;
break; break;
@@ -91,9 +93,9 @@ function toConcatStream(src, bundledFileHeader, sources, dest) {
contents: bundledFileHeader contents: bundledFileHeader
}); });
} }
var treatedSources = sources.map(function (source) { const treatedSources = sources.map(function (source) {
var root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : ''; const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : '';
var base = source.path ? root + ("/" + src) : ''; const base = source.path ? root + `/${src}` : undefined;
return new VinylFile({ return new VinylFile({
path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake', path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake',
base: base, base: base,
@@ -102,7 +104,8 @@ function toConcatStream(src, bundledFileHeader, sources, dest) {
}); });
return es.readArray(treatedSources) return es.readArray(treatedSources)
.pipe(useSourcemaps ? util.loadSourcemaps() : es.through()) .pipe(useSourcemaps ? util.loadSourcemaps() : es.through())
.pipe(concat(dest)); .pipe(concat(dest))
.pipe(stats_1.createStatsStream(dest));
} }
function toBundleStream(src, bundledFileHeader, bundles) { function toBundleStream(src, bundledFileHeader, bundles) {
return es.merge(bundles.map(function (bundle) { return es.merge(bundles.map(function (bundle) {
@@ -110,33 +113,33 @@ function toBundleStream(src, bundledFileHeader, bundles) {
})); }));
} }
function optimizeTask(opts) { function optimizeTask(opts) {
var src = opts.src; const src = opts.src;
var entryPoints = opts.entryPoints; const entryPoints = opts.entryPoints;
var otherSources = opts.otherSources; const otherSources = opts.otherSources;
var resources = opts.resources; const resources = opts.resources;
var loaderConfig = opts.loaderConfig; const loaderConfig = opts.loaderConfig;
var bundledFileHeader = opts.header; const bundledFileHeader = opts.header;
var bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader); const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
var out = opts.out; const out = opts.out;
return function () { return function () {
var bundlesStream = es.through(); // this stream will contain the bundled files const bundlesStream = es.through(); // this stream will contain the bundled files
var resourcesStream = es.through(); // this stream will contain the resources const resourcesStream = es.through(); // this stream will contain the resources
var bundleInfoStream = es.through(); // this stream will contain bundleInfo.json const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
bundle.bundle(entryPoints, loaderConfig, function (err, result) { bundle.bundle(entryPoints, loaderConfig, function (err, result) {
if (err) { if (err || !result) {
return bundlesStream.emit('error', JSON.stringify(err)); return bundlesStream.emit('error', JSON.stringify(err));
} }
toBundleStream(src, bundledFileHeader, result.files).pipe(bundlesStream); toBundleStream(src, bundledFileHeader, result.files).pipe(bundlesStream);
// Remove css inlined resources // Remove css inlined resources
var filteredResources = resources.slice(); const filteredResources = resources.slice();
result.cssInlinedResources.forEach(function (resource) { result.cssInlinedResources.forEach(function (resource) {
if (process.env['VSCODE_BUILD_VERBOSE']) { if (process.env['VSCODE_BUILD_VERBOSE']) {
log('optimizer', 'excluding inlined: ' + resource); log('optimizer', 'excluding inlined: ' + resource);
} }
filteredResources.push('!' + resource); filteredResources.push('!' + resource);
}); });
gulp.src(filteredResources, { base: "" + src }).pipe(resourcesStream); gulp.src(filteredResources, { base: `${src}` }).pipe(resourcesStream);
var bundleInfoArray = []; const bundleInfoArray = [];
if (opts.bundleInfo) { if (opts.bundleInfo) {
bundleInfoArray.push(new VinylFile({ bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json', path: 'bundleInfo.json',
@@ -146,9 +149,9 @@ function optimizeTask(opts) {
} }
es.readArray(bundleInfoArray).pipe(bundleInfoStream); es.readArray(bundleInfoArray).pipe(bundleInfoStream);
}); });
var otherSourcesStream = es.through(); const otherSourcesStream = es.through();
var otherSourcesStreamArr = []; const otherSourcesStreamArr = [];
gulp.src(otherSources, { base: "" + src }) gulp.src(otherSources, { base: `${src}` })
.pipe(es.through(function (data) { .pipe(es.through(function (data) {
otherSourcesStreamArr.push(toConcatStream(src, bundledFileHeader, [data], data.relative)); otherSourcesStreamArr.push(toConcatStream(src, bundledFileHeader, [data], data.relative));
}, function () { }, function () {
@@ -159,13 +162,17 @@ function optimizeTask(opts) {
es.merge(otherSourcesStreamArr).pipe(otherSourcesStream); es.merge(otherSourcesStreamArr).pipe(otherSourcesStream);
} }
})); }));
var result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, otherSourcesStream, resourcesStream, bundleInfoStream); const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, otherSourcesStream, resourcesStream, bundleInfoStream);
return result return result
.pipe(sourcemaps.write('./', { .pipe(sourcemaps.write('./', {
sourceRoot: null, sourceRoot: undefined,
addComment: true, addComment: true,
includeContent: true includeContent: true
})) }))
.pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({
fileHeader: bundledFileHeader,
languages: opts.languages
}) : es.through())
.pipe(gulp.dest(out)); .pipe(gulp.dest(out));
}; };
} }
@@ -175,14 +182,14 @@ exports.optimizeTask = optimizeTask;
* to have a file "context" to include our copyright only once per file. * to have a file "context" to include our copyright only once per file.
*/ */
function uglifyWithCopyrights() { function uglifyWithCopyrights() {
var preserveComments = function (f) { const preserveComments = (f) => {
return function (node, comment) { return (_node, comment) => {
var text = comment.value; const text = comment.value;
var type = comment.type; const type = comment.type;
if (/@minifier_do_not_preserve/.test(text)) { if (/@minifier_do_not_preserve/.test(text)) {
return false; return false;
} }
var isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text); const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text);
if (isOurCopyright) { if (isOurCopyright) {
if (f.__hasOurCopyright) { if (f.__hasOurCopyright) {
return false; return false;
@@ -200,10 +207,10 @@ function uglifyWithCopyrights() {
return false; return false;
}; };
}; };
var minify = composer(uglifyes); const minify = composer(uglifyes);
var input = es.through(); const input = es.through();
var output = input const output = input
.pipe(flatmap(function (stream, f) { .pipe(flatmap((stream, f) => {
return stream.pipe(minify({ return stream.pipe(minify({
output: { output: {
comments: preserveComments(f), comments: preserveComments(f),
@@ -214,18 +221,18 @@ function uglifyWithCopyrights() {
return es.duplex(input, output); return es.duplex(input, output);
} }
function minifyTask(src, sourceMapBaseUrl) { function minifyTask(src, sourceMapBaseUrl) {
var sourceMappingURL = sourceMapBaseUrl && (function (f) { return sourceMapBaseUrl + "/" + f.relative + ".map"; }); const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
return function (cb) { return cb => {
var jsFilter = filter('**/*.js', { restore: true }); const jsFilter = filter('**/*.js', { restore: true });
var cssFilter = filter('**/*.css', { restore: true }); const cssFilter = filter('**/*.css', { restore: true });
pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.write('./', { pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.write('./', {
sourceMappingURL: sourceMappingURL, sourceMappingURL,
sourceRoot: null, sourceRoot: undefined,
includeContent: true, includeContent: true,
addComment: true addComment: true
}), gulp.dest(src + '-min'), function (err) { }), gulp.dest(src + '-min'), (err) => {
if (err instanceof uglify.GulpUglifyError) { if (err instanceof uglify.GulpUglifyError) {
console.error("Uglify error in '" + (err.cause && err.cause.filename) + "'"); console.error(`Uglify error in '${err.cause && err.cause.filename}'`);
} }
cb(err); cb(err);
}); });

View File

@@ -5,24 +5,25 @@
'use strict'; 'use strict';
import * as path from 'path'; import * as es from 'event-stream';
import * as gulp from 'gulp'; import * as gulp from 'gulp';
import * as sourcemaps from 'gulp-sourcemaps'; import * as concat from 'gulp-concat';
import * as filter from 'gulp-filter';
import * as minifyCSS from 'gulp-cssnano'; import * as minifyCSS from 'gulp-cssnano';
import * as filter from 'gulp-filter';
import * as flatmap from 'gulp-flatmap';
import * as sourcemaps from 'gulp-sourcemaps';
import * as uglify from 'gulp-uglify'; import * as uglify from 'gulp-uglify';
import * as composer from 'gulp-uglify/composer'; import * as composer from 'gulp-uglify/composer';
import * as uglifyes from 'uglify-es';
import * as es from 'event-stream';
import * as concat from 'gulp-concat';
import * as VinylFile from 'vinyl';
import * as bundle from './bundle';
import * as util from './util';
import * as gulpUtil from 'gulp-util'; import * as gulpUtil from 'gulp-util';
import * as flatmap from 'gulp-flatmap'; import * as path from 'path';
import * as pump from 'pump'; import * as pump from 'pump';
import * as sm from 'source-map'; import * as sm from 'source-map';
import { Language } from './i18n'; import * as uglifyes from 'uglify-es';
import * as VinylFile from 'vinyl';
import * as bundle from './bundle';
import { Language, processNlsFiles } from './i18n';
import { createStatsStream } from './stats';
import * as util from './util';
const REPO_ROOT_PATH = path.join(__dirname, '../..'); const REPO_ROOT_PATH = path.join(__dirname, '../..');
@@ -32,7 +33,7 @@ function log(prefix: string, message: string): void {
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
export function loaderConfig(emptyPaths?: string[]) { export function loaderConfig(emptyPaths?: string[]) {
const result = { const result: any = {
paths: { paths: {
'vs': 'out-build/vs', 'vs': 'out-build/vs',
'sql': 'out-build/sql', 'sql': 'out-build/sql',
@@ -72,7 +73,7 @@ function loader(src: string, bundledFileHeader: string, bundleLoader: boolean):
isFirst = false; isFirst = false;
this.emit('data', new VinylFile({ this.emit('data', new VinylFile({
path: 'fake', path: 'fake',
base: '', base: undefined,
contents: Buffer.from(bundledFileHeader) contents: Buffer.from(bundledFileHeader)
})); }));
this.emit('data', data); this.emit('data', data);
@@ -112,7 +113,7 @@ function toConcatStream(src: string, bundledFileHeader: string, sources: bundle.
const treatedSources = sources.map(function (source) { const treatedSources = sources.map(function (source) {
const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : ''; const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : '';
const base = source.path ? root + `/${src}` : ''; const base = source.path ? root + `/${src}` : undefined;
return new VinylFile({ return new VinylFile({
path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake', path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake',
@@ -123,10 +124,11 @@ function toConcatStream(src: string, bundledFileHeader: string, sources: bundle.
return es.readArray(treatedSources) return es.readArray(treatedSources)
.pipe(useSourcemaps ? util.loadSourcemaps() : es.through()) .pipe(useSourcemaps ? util.loadSourcemaps() : es.through())
.pipe(concat(dest)); .pipe(concat(dest))
.pipe(createStatsStream(dest));
} }
function toBundleStream(src:string, bundledFileHeader: string, bundles: bundle.IConcatFile[]): NodeJS.ReadWriteStream { function toBundleStream(src: string, bundledFileHeader: string, bundles: bundle.IConcatFile[]): NodeJS.ReadWriteStream {
return es.merge(bundles.map(function (bundle) { return es.merge(bundles.map(function (bundle) {
return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest); return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest);
})); }));
@@ -188,7 +190,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr
const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
bundle.bundle(entryPoints, loaderConfig, function (err, result) { bundle.bundle(entryPoints, loaderConfig, function (err, result) {
if (err) { return bundlesStream.emit('error', JSON.stringify(err)); } if (err || !result) { return bundlesStream.emit('error', JSON.stringify(err)); }
toBundleStream(src, bundledFileHeader, result.files).pipe(bundlesStream); toBundleStream(src, bundledFileHeader, result.files).pipe(bundlesStream);
@@ -237,10 +239,14 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr
return result return result
.pipe(sourcemaps.write('./', { .pipe(sourcemaps.write('./', {
sourceRoot: null, sourceRoot: undefined,
addComment: true, addComment: true,
includeContent: true includeContent: true
})) }))
.pipe(opts.languages && opts.languages.length ? processNlsFiles({
fileHeader: bundledFileHeader,
languages: opts.languages
}) : es.through())
.pipe(gulp.dest(out)); .pipe(gulp.dest(out));
}; };
} }
@@ -254,7 +260,7 @@ declare class FileWithCopyright extends VinylFile {
*/ */
function uglifyWithCopyrights(): NodeJS.ReadWriteStream { function uglifyWithCopyrights(): NodeJS.ReadWriteStream {
const preserveComments = (f: FileWithCopyright) => { const preserveComments = (f: FileWithCopyright) => {
return (node, comment: { value: string; type: string; }) => { return (_node: any, comment: { value: string; type: string; }) => {
const text = comment.value; const text = comment.value;
const type = comment.type; const type = comment.type;
@@ -282,7 +288,7 @@ function uglifyWithCopyrights(): NodeJS.ReadWriteStream {
}; };
}; };
const minify = composer(uglifyes); const minify = (composer as any)(uglifyes);
const input = es.through(); const input = es.through();
const output = input const output = input
.pipe(flatmap((stream, f) => { .pipe(flatmap((stream, f) => {
@@ -298,7 +304,7 @@ function uglifyWithCopyrights(): NodeJS.ReadWriteStream {
} }
export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => void { export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => void {
const sourceMappingURL = sourceMapBaseUrl && (f => `${sourceMapBaseUrl}/${f.relative}.map`); const sourceMappingURL = sourceMapBaseUrl ? ((f: any) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
return cb => { return cb => {
const jsFilter = filter('**/*.js', { restore: true }); const jsFilter = filter('**/*.js', { restore: true });
@@ -315,13 +321,13 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) =>
cssFilter.restore, cssFilter.restore,
sourcemaps.write('./', { sourcemaps.write('./', {
sourceMappingURL, sourceMappingURL,
sourceRoot: null, sourceRoot: undefined,
includeContent: true, includeContent: true,
addComment: true addComment: true
}), } as any),
gulp.dest(src + '-min') gulp.dest(src + '-min')
, (err: any) => { , (err: any) => {
if (err instanceof uglify.GulpUglifyError) { if (err instanceof (uglify as any).GulpUglifyError) {
console.error(`Uglify error in '${err.cause && err.cause.filename}'`); console.error(`Uglify error in '${err.cause && err.cause.filename}'`);
} }

View File

@@ -4,20 +4,20 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var es = require("event-stream"); const es = require("event-stream");
var _ = require("underscore"); const _ = require("underscore");
var util = require("gulp-util"); const util = require("gulp-util");
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var allErrors = []; const allErrors = [];
var startTime = null; let startTime = null;
var count = 0; let count = 0;
function onStart() { function onStart() {
if (count++ > 0) { if (count++ > 0) {
return; return;
} }
startTime = new Date().getTime(); startTime = new Date().getTime();
util.log("Starting " + util.colors.green('compilation') + "..."); util.log(`Starting ${util.colors.green('compilation')}...`);
} }
function onEnd() { function onEnd() {
if (--count > 0) { if (--count > 0) {
@@ -25,7 +25,7 @@ function onEnd() {
} }
log(); log();
} }
var buildLogPath = path.join(path.dirname(path.dirname(__dirname)), '.build', 'log'); const buildLogPath = path.join(path.dirname(path.dirname(__dirname)), '.build', 'log');
try { try {
fs.mkdirSync(path.dirname(buildLogPath)); fs.mkdirSync(path.dirname(buildLogPath));
} }
@@ -33,61 +33,52 @@ catch (err) {
// ignore // ignore
} }
function log() { function log() {
var errors = _.flatten(allErrors); const errors = _.flatten(allErrors);
var seen = new Set(); const seen = new Set();
errors.map(function (err) { errors.map(err => {
if (!seen.has(err)) { if (!seen.has(err)) {
seen.add(err); seen.add(err);
util.log(util.colors.red('Error') + ": " + err); util.log(`${util.colors.red('Error')}: ${err}`);
} }
}); });
var regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/; const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/;
var messages = errors const messages = errors
.map(function (err) { return regex.exec(err); }) .map(err => regex.exec(err))
.filter(function (match) { return !!match; }) .filter(match => !!match)
.map(function (_a) { .map(x => x)
var path = _a[1], line = _a[2], column = _a[3], message = _a[4]; .map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message }));
return ({ path: path, line: parseInt(line), column: parseInt(column), message: message });
});
try { try {
fs.writeFileSync(buildLogPath, JSON.stringify(messages)); fs.writeFileSync(buildLogPath, JSON.stringify(messages));
} }
catch (err) { catch (err) {
//noop //noop
} }
util.log("Finished " + util.colors.green('compilation') + " with " + errors.length + " errors after " + util.colors.magenta((new Date().getTime() - startTime) + ' ms')); util.log(`Finished ${util.colors.green('compilation')} with ${errors.length} errors after ${util.colors.magenta((new Date().getTime() - startTime) + ' ms')}`);
} }
function createReporter() { function createReporter() {
var errors = []; const errors = [];
allErrors.push(errors); allErrors.push(errors);
var ReportFunc = /** @class */ (function () { const result = (err) => errors.push(err);
function ReportFunc(err) { result.hasErrors = () => errors.length > 0;
errors.push(err); result.end = (emitError) => {
} errors.length = 0;
ReportFunc.hasErrors = function () { onStart();
return errors.length > 0; return es.through(undefined, function () {
}; onEnd();
ReportFunc.end = function (emitError) { if (emitError && errors.length > 0) {
errors.length = 0; if (!errors.__logged__) {
onStart(); log();
return es.through(null, function () {
onEnd();
if (emitError && errors.length > 0) {
errors.__logged__ = true;
if (!errors.__logged__) {
log();
}
var err = new Error("Found " + errors.length + " errors");
err.__reporter__ = true;
this.emit('error', err);
} }
else { errors.__logged__ = true;
this.emit('end'); const err = new Error(`Found ${errors.length} errors`);
} err.__reporter__ = true;
}); this.emit('error', err);
}; }
return ReportFunc; else {
}()); this.emit('end');
return ReportFunc; }
});
};
return result;
} }
exports.createReporter = createReporter; exports.createReporter = createReporter;

View File

@@ -12,7 +12,7 @@ import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
const allErrors: string[][] = []; const allErrors: string[][] = [];
let startTime: number = null; let startTime: number | null = null;
let count = 0; let count = 0;
function onStart(): void { function onStart(): void {
@@ -55,6 +55,7 @@ function log(): void {
const messages = errors const messages = errors
.map(err => regex.exec(err)) .map(err => regex.exec(err))
.filter(match => !!match) .filter(match => !!match)
.map(x => x as string[])
.map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message })); .map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message }));
try { try {
@@ -64,7 +65,7 @@ function log(): void {
//noop //noop
} }
util.log(`Finished ${util.colors.green('compilation')} with ${errors.length} errors after ${util.colors.magenta((new Date().getTime() - startTime) + ' ms')}`); util.log(`Finished ${util.colors.green('compilation')} with ${errors.length} errors after ${util.colors.magenta((new Date().getTime() - startTime!) + ' ms')}`);
} }
export interface IReporter { export interface IReporter {
@@ -77,38 +78,32 @@ export function createReporter(): IReporter {
const errors: string[] = []; const errors: string[] = [];
allErrors.push(errors); allErrors.push(errors);
class ReportFunc { const result = (err: string) => errors.push(err);
constructor(err: string) {
errors.push(err);
}
static hasErrors(): boolean { result.hasErrors = () => errors.length > 0;
return errors.length > 0;
}
static end(emitError: boolean): NodeJS.ReadWriteStream { result.end = (emitError: boolean): NodeJS.ReadWriteStream => {
errors.length = 0; errors.length = 0;
onStart(); onStart();
return es.through(null, function () { return es.through(undefined, function () {
onEnd(); onEnd();
if (emitError && errors.length > 0) { if (emitError && errors.length > 0) {
(errors as any).__logged__ = true; if (!(errors as any).__logged__) {
log();
if (!(errors as any).__logged__) {
log();
}
const err = new Error(`Found ${errors.length} errors`);
(err as any).__reporter__ = true;
this.emit('error', err);
} else {
this.emit('end');
} }
});
}
}
return <IReporter><any>ReportFunc; (errors as any).__logged__ = true;
const err = new Error(`Found ${errors.length} errors`);
(err as any).__reporter__ = true;
this.emit('error', err);
} else {
this.emit('end');
}
});
};
return result;
} }

View File

@@ -5,35 +5,51 @@
'use strict'; 'use strict';
var snaps; var snaps;
(function (snaps) { (function (snaps) {
var fs = require('fs'); const fs = require('fs');
var path = require('path'); const path = require('path');
var os = require('os'); const os = require('os');
var cp = require('child_process'); const cp = require('child_process');
var mksnapshot = path.join(__dirname, "../../node_modules/.bin/" + (process.platform === 'win32' ? 'mksnapshot.cmd' : 'mksnapshot')); const mksnapshot = path.join(__dirname, `../../node_modules/.bin/${process.platform === 'win32' ? 'mksnapshot.cmd' : 'mksnapshot'}`);
var product = require('../../product.json'); const product = require('../../product.json');
var arch = (process.argv.join('').match(/--arch=(.*)/) || [])[1]; const arch = (process.argv.join('').match(/--arch=(.*)/) || [])[1];
// //
var loaderFilepath; let loaderFilepath;
var startupBlobFilepath; let startupBlobFilepath;
switch (process.platform) { switch (process.platform) {
case 'darwin': case 'darwin':
loaderFilepath = "VSCode-darwin/" + product.nameLong + ".app/Contents/Resources/app/out/vs/loader.js"; loaderFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Resources/app/out/vs/loader.js`;
startupBlobFilepath = "VSCode-darwin/" + product.nameLong + ".app/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin"; startupBlobFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin`;
break; break;
case 'win32': case 'win32':
case 'linux': case 'linux':
loaderFilepath = "VSCode-" + process.platform + "-" + arch + "/resources/app/out/vs/loader.js"; loaderFilepath = `VSCode-${process.platform}-${arch}/resources/app/out/vs/loader.js`;
startupBlobFilepath = "VSCode-" + process.platform + "-" + arch + "/snapshot_blob.bin"; startupBlobFilepath = `VSCode-${process.platform}-${arch}/snapshot_blob.bin`;
break;
default:
throw new Error('Unknown platform');
} }
loaderFilepath = path.join(__dirname, '../../../', loaderFilepath); loaderFilepath = path.join(__dirname, '../../../', loaderFilepath);
startupBlobFilepath = path.join(__dirname, '../../../', startupBlobFilepath); startupBlobFilepath = path.join(__dirname, '../../../', startupBlobFilepath);
snapshotLoader(loaderFilepath, startupBlobFilepath); snapshotLoader(loaderFilepath, startupBlobFilepath);
function snapshotLoader(loaderFilepath, startupBlobFilepath) { function snapshotLoader(loaderFilepath, startupBlobFilepath) {
var inputFile = fs.readFileSync(loaderFilepath); const inputFile = fs.readFileSync(loaderFilepath);
var wrappedInputFile = "\n\t\tvar Monaco_Loader_Init;\n\t\t(function() {\n\t\t\tvar doNotInitLoader = true;\n\t\t\t" + inputFile.toString() + ";\n\t\t\tMonaco_Loader_Init = function() {\n\t\t\t\tAMDLoader.init();\n\t\t\t\tCSSLoaderPlugin.init();\n\t\t\t\tNLSLoaderPlugin.init();\n\n\t\t\t\treturn { define, require };\n\t\t\t}\n\t\t})();\n\t\t"; const wrappedInputFile = `
var wrappedInputFilepath = path.join(os.tmpdir(), 'wrapped-loader.js'); var Monaco_Loader_Init;
(function() {
var doNotInitLoader = true;
${inputFile.toString()};
Monaco_Loader_Init = function() {
AMDLoader.init();
CSSLoaderPlugin.init();
NLSLoaderPlugin.init();
return { define, require };
}
})();
`;
const wrappedInputFilepath = path.join(os.tmpdir(), 'wrapped-loader.js');
console.log(wrappedInputFilepath); console.log(wrappedInputFilepath);
fs.writeFileSync(wrappedInputFilepath, wrappedInputFile); fs.writeFileSync(wrappedInputFilepath, wrappedInputFile);
cp.execFileSync(mksnapshot, [wrappedInputFilepath, "--startup_blob", startupBlobFilepath]); cp.execFileSync(mksnapshot, [wrappedInputFilepath, `--startup_blob`, startupBlobFilepath]);
} }
})(snaps || (snaps = {})); })(snaps || (snaps = {}));

View File

@@ -30,6 +30,10 @@ namespace snaps {
case 'linux': case 'linux':
loaderFilepath = `VSCode-${process.platform}-${arch}/resources/app/out/vs/loader.js`; loaderFilepath = `VSCode-${process.platform}-${arch}/resources/app/out/vs/loader.js`;
startupBlobFilepath = `VSCode-${process.platform}-${arch}/snapshot_blob.bin`; startupBlobFilepath = `VSCode-${process.platform}-${arch}/snapshot_blob.bin`;
break;
default:
throw new Error('Unknown platform');
} }
loaderFilepath = path.join(__dirname, '../../../', loaderFilepath); loaderFilepath = path.join(__dirname, '../../../', loaderFilepath);

View File

@@ -4,14 +4,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript"); const ts = require("typescript");
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var tss = require("./treeshaking"); const tss = require("./treeshaking");
var REPO_ROOT = path.join(__dirname, '../../'); const REPO_ROOT = path.join(__dirname, '../../');
var SRC_DIR = path.join(REPO_ROOT, 'src'); const SRC_DIR = path.join(REPO_ROOT, 'src');
var OUT_EDITOR = path.join(REPO_ROOT, 'out-editor'); let dirCache = {};
var dirCache = {};
function writeFile(filePath, contents) { function writeFile(filePath, contents) {
function ensureDirs(dirPath) { function ensureDirs(dirPath) {
if (dirCache[dirPath]) { if (dirCache[dirPath]) {
@@ -28,32 +27,49 @@ function writeFile(filePath, contents) {
fs.writeFileSync(filePath, contents); fs.writeFileSync(filePath, contents);
} }
function extractEditor(options) { function extractEditor(options) {
var result = tss.shake(options); const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString());
for (var fileName in result) { let compilerOptions;
if (tsConfig.extends) {
compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions);
}
else {
compilerOptions = tsConfig.compilerOptions;
}
tsConfig.compilerOptions = compilerOptions;
compilerOptions.noUnusedLocals = false;
compilerOptions.preserveConstEnums = false;
compilerOptions.declaration = false;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic;
delete compilerOptions.types;
delete tsConfig.extends;
tsConfig.exclude = [];
options.compilerOptions = compilerOptions;
let result = tss.shake(options);
for (let fileName in result) {
if (result.hasOwnProperty(fileName)) { if (result.hasOwnProperty(fileName)) {
writeFile(path.join(options.destRoot, fileName), result[fileName]); writeFile(path.join(options.destRoot, fileName), result[fileName]);
} }
} }
var copied = {}; let copied = {};
var copyFile = function (fileName) { const copyFile = (fileName) => {
if (copied[fileName]) { if (copied[fileName]) {
return; return;
} }
copied[fileName] = true; copied[fileName] = true;
var srcPath = path.join(options.sourcesRoot, fileName); const srcPath = path.join(options.sourcesRoot, fileName);
var dstPath = path.join(options.destRoot, fileName); const dstPath = path.join(options.destRoot, fileName);
writeFile(dstPath, fs.readFileSync(srcPath)); writeFile(dstPath, fs.readFileSync(srcPath));
}; };
var writeOutputFile = function (fileName, contents) { const writeOutputFile = (fileName, contents) => {
writeFile(path.join(options.destRoot, fileName), contents); writeFile(path.join(options.destRoot, fileName), contents);
}; };
for (var fileName in result) { for (let fileName in result) {
if (result.hasOwnProperty(fileName)) { if (result.hasOwnProperty(fileName)) {
var fileContents = result[fileName]; const fileContents = result[fileName];
var info = ts.preProcessFile(fileContents); const info = ts.preProcessFile(fileContents);
for (var i = info.importedFiles.length - 1; i >= 0; i--) { for (let i = info.importedFiles.length - 1; i >= 0; i--) {
var importedFileName = info.importedFiles[i].fileName; const importedFileName = info.importedFiles[i].fileName;
var importedFilePath = void 0; let importedFilePath;
if (/^vs\/css!/.test(importedFileName)) { if (/^vs\/css!/.test(importedFileName)) {
importedFilePath = importedFileName.substr('vs/css!'.length) + '.css'; importedFilePath = importedFileName.substr('vs/css!'.length) + '.css';
} }
@@ -74,215 +90,188 @@ function extractEditor(options) {
} }
} }
} }
var tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); delete tsConfig.compilerOptions.moduleResolution;
tsConfig.compilerOptions.noUnusedLocals = false;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
[ [
'vs/css.build.js', 'vs/css.build.js',
'vs/css.d.ts', 'vs/css.d.ts',
'vs/css.js', 'vs/css.js',
'vs/loader.js', 'vs/loader.js',
'vs/monaco.d.ts',
'vs/nls.build.js', 'vs/nls.build.js',
'vs/nls.d.ts', 'vs/nls.d.ts',
'vs/nls.js', 'vs/nls.js',
'vs/nls.mock.ts', 'vs/nls.mock.ts',
'typings/lib.ie11_safe_es6.d.ts',
'typings/thenable.d.ts',
'typings/es6-promise.d.ts',
'typings/require.d.ts',
].forEach(copyFile); ].forEach(copyFile);
} }
exports.extractEditor = extractEditor; exports.extractEditor = extractEditor;
function createESMSourcesAndResources(options) { function createESMSourcesAndResources2(options) {
var OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); const SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder);
var OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder);
var in_queue = Object.create(null); const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder);
var queue = []; const getDestAbsoluteFilePath = (file) => {
var enqueue = function (module) { let dest = options.renames[file.replace(/\\/g, '/')] || file;
if (in_queue[module]) { if (dest === 'tsconfig.json') {
return; return path.join(OUT_FOLDER, `tsconfig.json`);
} }
in_queue[module] = true; if (/\.ts$/.test(dest)) {
queue.push(module); return path.join(OUT_FOLDER, dest);
}
return path.join(OUT_RESOURCES_FOLDER, dest);
}; };
var seenDir = {}; const allFiles = walkDirRecursive(SRC_FOLDER);
var createDirectoryRecursive = function (dir) { for (let i = 0; i < allFiles.length; i++) {
if (seenDir[dir]) { const file = allFiles[i];
return; if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) {
continue;
} }
var lastSlash = dir.lastIndexOf('/'); if (file === 'tsconfig.json') {
if (lastSlash === -1) { const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
lastSlash = dir.lastIndexOf('\\'); tsConfig.compilerOptions.module = 'es6';
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
continue;
} }
if (lastSlash !== -1) { if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file)) {
createDirectoryRecursive(dir.substring(0, lastSlash)); // Transport the files directly
write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file)));
continue;
} }
seenDir[dir] = true; if (/\.ts$/.test(file)) {
try { // Transform the .ts file
fs.mkdirSync(dir); let fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString();
} const info = ts.preProcessFile(fileContents);
catch (err) { } for (let i = info.importedFiles.length - 1; i >= 0; i--) {
}; const importedFilename = info.importedFiles[i].fileName;
seenDir[REPO_ROOT] = true; const pos = info.importedFiles[i].pos;
var toggleComments = function (fileContents) { const end = info.importedFiles[i].end;
var lines = fileContents.split(/\r\n|\r|\n/); let importedFilepath;
var mode = 0; if (/^vs\/css!/.test(importedFilename)) {
for (var i = 0; i < lines.length; i++) { importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
var line = lines[i];
if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
} }
if (/\/\/ ESM-uncomment-begin/.test(line)) { else {
mode = 2; importedFilepath = importedFilename;
continue;
} }
continue; if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(file), importedFilepath);
}
let relativePath;
if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) {
relativePath = '../' + path.basename(path.dirname(file));
}
else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(file)));
}
else {
relativePath = path.relative(path.dirname(file), importedFilepath);
}
relativePath = relativePath.replace(/\\/g, '/');
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1));
} }
if (mode === 1) { fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
if (/\/\/ ESM-comment-end/.test(line)) { return `import * as ${m1} from ${m2};`;
mode = 0; });
continue; write(getDestAbsoluteFilePath(file), fileContents);
} continue;
lines[i] = '// ' + line; }
continue; console.log(`UNKNOWN FILE: ${file}`);
}
function walkDirRecursive(dir) {
if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') {
dir += '/';
}
let result = [];
_walkDirRecursive(dir, result, dir.length);
return result;
}
function _walkDirRecursive(dir, result, trimPos) {
const files = fs.readdirSync(dir);
for (let i = 0; i < files.length; i++) {
const file = path.join(dir, files[i]);
if (fs.statSync(file).isDirectory()) {
_walkDirRecursive(file, result, trimPos);
} }
if (mode === 2) { else {
if (/\/\/ ESM-uncomment-end/.test(line)) { result.push(file.substr(trimPos));
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
} }
} }
return lines.join('\n'); }
}; function write(absoluteFilePath, contents) {
var write = function (filePath, contents) { if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) {
var absoluteFilePath;
if (/\.ts$/.test(filePath)) {
absoluteFilePath = path.join(OUT_FOLDER, filePath);
}
else {
absoluteFilePath = path.join(OUT_RESOURCES_FOLDER, filePath);
}
createDirectoryRecursive(path.dirname(absoluteFilePath));
if (/(\.ts$)|(\.js$)/.test(filePath)) {
contents = toggleComments(contents.toString()); contents = toggleComments(contents.toString());
} }
fs.writeFileSync(absoluteFilePath, contents); writeFile(absoluteFilePath, contents);
}; function toggleComments(fileContents) {
options.entryPoints.forEach(function (entryPoint) { return enqueue(entryPoint); }); let lines = fileContents.split(/\r\n|\r|\n/);
while (queue.length > 0) { let mode = 0;
var module_1 = queue.shift(); for (let i = 0; i < lines.length; i++) {
if (transportCSS(module_1, enqueue, write)) { const line = lines[i];
continue; if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
}
if (/\/\/ ESM-uncomment-begin/.test(line)) {
mode = 2;
continue;
}
continue;
}
if (mode === 1) {
if (/\/\/ ESM-comment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = '// ' + line;
continue;
}
if (mode === 2) {
if (/\/\/ ESM-uncomment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
}
}
return lines.join('\n');
} }
if (transportResource(options, module_1, enqueue, write)) {
continue;
}
if (transportDTS(options, module_1, enqueue, write)) {
continue;
}
var filename = void 0;
if (options.redirects[module_1]) {
filename = path.join(SRC_DIR, options.redirects[module_1] + '.ts');
}
else {
filename = path.join(SRC_DIR, module_1 + '.ts');
}
var fileContents = fs.readFileSync(filename).toString();
var info = ts.preProcessFile(fileContents);
for (var i = info.importedFiles.length - 1; i >= 0; i--) {
var importedFilename = info.importedFiles[i].fileName;
var pos = info.importedFiles[i].pos;
var end = info.importedFiles[i].end;
var importedFilepath = void 0;
if (/^vs\/css!/.test(importedFilename)) {
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
}
else {
importedFilepath = importedFilename;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(module_1), importedFilepath);
}
enqueue(importedFilepath);
var relativePath = void 0;
if (importedFilepath === path.dirname(module_1)) {
relativePath = '../' + path.basename(path.dirname(module_1));
}
else if (importedFilepath === path.dirname(path.dirname(module_1))) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(module_1)));
}
else {
relativePath = path.relative(path.dirname(module_1), importedFilepath);
}
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1));
}
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
return "import * as " + m1 + " from " + m2 + ";";
});
fileContents = fileContents.replace(/Thenable/g, 'PromiseLike');
write(module_1 + '.ts', fileContents);
} }
var esm_opts = {
"compilerOptions": {
"outDir": path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER),
"rootDir": "src",
"module": "es6",
"target": "es5",
"experimentalDecorators": true,
"lib": [
"dom",
"es5",
"es2015.collection",
"es2015.promise"
],
"types": []
}
};
fs.writeFileSync(path.join(path.dirname(OUT_FOLDER), 'tsconfig.json'), JSON.stringify(esm_opts, null, '\t'));
var monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString();
fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts);
} }
exports.createESMSourcesAndResources = createESMSourcesAndResources; exports.createESMSourcesAndResources2 = createESMSourcesAndResources2;
function transportCSS(module, enqueue, write) { function transportCSS(module, enqueue, write) {
if (!/\.css/.test(module)) { if (!/\.css/.test(module)) {
return false; return false;
} }
var filename = path.join(SRC_DIR, module); const filename = path.join(SRC_DIR, module);
var fileContents = fs.readFileSync(filename).toString(); const fileContents = fs.readFileSync(filename).toString();
var inlineResources = 'base64'; // see https://github.com/Microsoft/monaco-editor/issues/148 const inlineResources = 'base64'; // see https://github.com/Microsoft/monaco-editor/issues/148
var inlineResourcesLimit = 300000; //3000; // see https://github.com/Microsoft/monaco-editor/issues/336 const inlineResourcesLimit = 300000; //3000; // see https://github.com/Microsoft/monaco-editor/issues/336
var newContents = _rewriteOrInlineUrls(fileContents, inlineResources === 'base64', inlineResourcesLimit); const newContents = _rewriteOrInlineUrls(fileContents, inlineResources === 'base64', inlineResourcesLimit);
write(module, newContents); write(module, newContents);
return true; return true;
function _rewriteOrInlineUrls(contents, forceBase64, inlineByteLimit) { function _rewriteOrInlineUrls(contents, forceBase64, inlineByteLimit) {
return _replaceURL(contents, function (url) { return _replaceURL(contents, (url) => {
var imagePath = path.join(path.dirname(module), url); let imagePath = path.join(path.dirname(module), url);
var fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath)); let fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath));
if (fileContents.length < inlineByteLimit) { if (fileContents.length < inlineByteLimit) {
var MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png'; const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
var DATA = ';base64,' + fileContents.toString('base64'); let DATA = ';base64,' + fileContents.toString('base64');
if (!forceBase64 && /\.svg$/.test(url)) { if (!forceBase64 && /\.svg$/.test(url)) {
// .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris // .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
var newText = fileContents.toString() let newText = fileContents.toString()
.replace(/"/g, '\'') .replace(/"/g, '\'')
.replace(/</g, '%3C') .replace(/</g, '%3C')
.replace(/>/g, '%3E') .replace(/>/g, '%3E')
.replace(/&/g, '%26') .replace(/&/g, '%26')
.replace(/#/g, '%23') .replace(/#/g, '%23')
.replace(/\s+/g, ' '); .replace(/\s+/g, ' ');
var encodedData = ',' + newText; let encodedData = ',' + newText;
if (encodedData.length < DATA.length) { if (encodedData.length < DATA.length) {
DATA = encodedData; DATA = encodedData;
} }
@@ -295,12 +284,8 @@ function transportCSS(module, enqueue, write) {
} }
function _replaceURL(contents, replacer) { function _replaceURL(contents, replacer) {
// Use ")" as the terminator as quotes are oftentimes not used at all // Use ")" as the terminator as quotes are oftentimes not used at all
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, function (_) { return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_, ...matches) => {
var matches = []; let url = matches[0];
for (var _i = 1; _i < arguments.length; _i++) {
matches[_i - 1] = arguments[_i];
}
var url = matches[0];
// Eliminate starting quotes (the initial whitespace is not captured) // Eliminate starting quotes (the initial whitespace is not captured)
if (url.charAt(0) === '"' || url.charAt(0) === '\'') { if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
url = url.substring(1); url = url.substring(1);
@@ -323,27 +308,3 @@ function transportCSS(module, enqueue, write) {
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle; return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
} }
} }
function transportResource(options, module, enqueue, write) {
if (!/\.svg/.test(module)) {
return false;
}
write(module, fs.readFileSync(path.join(SRC_DIR, module)));
return true;
}
function transportDTS(options, module, enqueue, write) {
if (options.redirects[module] && fs.existsSync(path.join(SRC_DIR, options.redirects[module] + '.ts'))) {
return false;
}
if (!fs.existsSync(path.join(SRC_DIR, module + '.d.ts'))) {
return false;
}
write(module + '.d.ts', fs.readFileSync(path.join(SRC_DIR, module + '.d.ts')));
var filename;
if (options.redirects[module]) {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, options.redirects[module] + '.js')));
}
else {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, module + '.js')));
}
return true;
}

View File

@@ -10,7 +10,6 @@ import * as tss from './treeshaking';
const REPO_ROOT = path.join(__dirname, '../../'); const REPO_ROOT = path.join(__dirname, '../../');
const SRC_DIR = path.join(REPO_ROOT, 'src'); const SRC_DIR = path.join(REPO_ROOT, 'src');
const OUT_EDITOR = path.join(REPO_ROOT, 'out-editor');
let dirCache: { [dir: string]: boolean; } = {}; let dirCache: { [dir: string]: boolean; } = {};
@@ -32,13 +31,33 @@ function writeFile(filePath: string, contents: Buffer | string): void {
} }
export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: string }): void { export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: string }): void {
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString());
let compilerOptions: { [key: string]: any };
if (tsConfig.extends) {
compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions);
} else {
compilerOptions = tsConfig.compilerOptions;
}
tsConfig.compilerOptions = compilerOptions;
compilerOptions.noUnusedLocals = false;
compilerOptions.preserveConstEnums = false;
compilerOptions.declaration = false;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic;
delete compilerOptions.types;
delete tsConfig.extends;
tsConfig.exclude = [];
options.compilerOptions = compilerOptions;
let result = tss.shake(options); let result = tss.shake(options);
for (let fileName in result) { for (let fileName in result) {
if (result.hasOwnProperty(fileName)) { if (result.hasOwnProperty(fileName)) {
writeFile(path.join(options.destRoot, fileName), result[fileName]); writeFile(path.join(options.destRoot, fileName), result[fileName]);
} }
} }
let copied: { [fileName:string]: boolean; } = {}; let copied: { [fileName: string]: boolean; } = {};
const copyFile = (fileName: string) => { const copyFile = (fileName: string) => {
if (copied[fileName]) { if (copied[fileName]) {
return; return;
@@ -48,7 +67,7 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
const dstPath = path.join(options.destRoot, fileName); const dstPath = path.join(options.destRoot, fileName);
writeFile(dstPath, fs.readFileSync(srcPath)); writeFile(dstPath, fs.readFileSync(srcPath));
}; };
const writeOutputFile = (fileName: string, contents: string) => { const writeOutputFile = (fileName: string, contents: string | Buffer) => {
writeFile(path.join(options.destRoot, fileName), contents); writeFile(path.join(options.destRoot, fileName), contents);
}; };
for (let fileName in result) { for (let fileName in result) {
@@ -80,8 +99,7 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
} }
} }
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); delete tsConfig.compilerOptions.moduleResolution;
tsConfig.compilerOptions.noUnusedLocals = false;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
[ [
@@ -89,203 +107,179 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
'vs/css.d.ts', 'vs/css.d.ts',
'vs/css.js', 'vs/css.js',
'vs/loader.js', 'vs/loader.js',
'vs/monaco.d.ts',
'vs/nls.build.js', 'vs/nls.build.js',
'vs/nls.d.ts', 'vs/nls.d.ts',
'vs/nls.js', 'vs/nls.js',
'vs/nls.mock.ts', 'vs/nls.mock.ts',
'typings/lib.ie11_safe_es6.d.ts',
'typings/thenable.d.ts',
'typings/es6-promise.d.ts',
'typings/require.d.ts',
].forEach(copyFile); ].forEach(copyFile);
} }
export interface IOptions { export interface IOptions2 {
entryPoints: string[]; srcFolder: string;
outFolder: string; outFolder: string;
outResourcesFolder: string; outResourcesFolder: string;
redirects: { [module: string]: string; }; ignores: string[];
renames: { [filename: string]: string; };
} }
export function createESMSourcesAndResources(options: IOptions): void { export function createESMSourcesAndResources2(options: IOptions2): void {
const SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder);
const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder);
const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder);
let in_queue: { [module: string]: boolean; } = Object.create(null); const getDestAbsoluteFilePath = (file: string): string => {
let queue: string[] = []; let dest = options.renames[file.replace(/\\/g, '/')] || file;
if (dest === 'tsconfig.json') {
const enqueue = (module: string) => { return path.join(OUT_FOLDER, `tsconfig.json`);
if (in_queue[module]) {
return;
} }
in_queue[module] = true; if (/\.ts$/.test(dest)) {
queue.push(module); return path.join(OUT_FOLDER, dest);
}
return path.join(OUT_RESOURCES_FOLDER, dest);
}; };
const seenDir: { [key: string]: boolean; } = {}; const allFiles = walkDirRecursive(SRC_FOLDER);
const createDirectoryRecursive = (dir: string) => { for (let i = 0; i < allFiles.length; i++) {
if (seenDir[dir]) { const file = allFiles[i];
return;
}
let lastSlash = dir.lastIndexOf('/'); if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) {
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
createDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
try { fs.mkdirSync(dir); } catch (err) { }
};
seenDir[REPO_ROOT] = true;
const toggleComments = (fileContents: string) => {
let lines = fileContents.split(/\r\n|\r|\n/);
let mode = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
}
if (/\/\/ ESM-uncomment-begin/.test(line)) {
mode = 2;
continue;
}
continue;
}
if (mode === 1) {
if (/\/\/ ESM-comment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = '// ' + line;
continue;
}
if (mode === 2) {
if (/\/\/ ESM-uncomment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
}
}
return lines.join('\n');
};
const write = (filePath: string, contents: string | Buffer) => {
let absoluteFilePath: string;
if (/\.ts$/.test(filePath)) {
absoluteFilePath = path.join(OUT_FOLDER, filePath);
} else {
absoluteFilePath = path.join(OUT_RESOURCES_FOLDER, filePath);
}
createDirectoryRecursive(path.dirname(absoluteFilePath));
if (/(\.ts$)|(\.js$)/.test(filePath)) {
contents = toggleComments(contents.toString());
}
fs.writeFileSync(absoluteFilePath, contents);
};
options.entryPoints.forEach((entryPoint) => enqueue(entryPoint));
while (queue.length > 0) {
const module = queue.shift();
if (transportCSS(module, enqueue, write)) {
continue;
}
if (transportResource(options, module, enqueue, write)) {
continue;
}
if (transportDTS(options, module, enqueue, write)) {
continue; continue;
} }
let filename: string; if (file === 'tsconfig.json') {
if (options.redirects[module]) { const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
filename = path.join(SRC_DIR, options.redirects[module] + '.ts'); tsConfig.compilerOptions.module = 'es6';
} else { tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
filename = path.join(SRC_DIR, module + '.ts'); write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
} continue;
let fileContents = fs.readFileSync(filename).toString();
const info = ts.preProcessFile(fileContents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
const importedFilename = info.importedFiles[i].fileName;
const pos = info.importedFiles[i].pos;
const end = info.importedFiles[i].end;
let importedFilepath: string;
if (/^vs\/css!/.test(importedFilename)) {
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
} else {
importedFilepath = importedFilename;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(module), importedFilepath);
}
enqueue(importedFilepath);
let relativePath: string;
if (importedFilepath === path.dirname(module)) {
relativePath = '../' + path.basename(path.dirname(module));
} else if (importedFilepath === path.dirname(path.dirname(module))) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(module)));
} else {
relativePath = path.relative(path.dirname(module), importedFilepath);
}
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (
fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1)
);
} }
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file)) {
return `import * as ${m1} from ${m2};`; // Transport the files directly
}); write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file)));
fileContents = fileContents.replace(/Thenable/g, 'PromiseLike'); continue;
}
write(module + '.ts', fileContents); if (/\.ts$/.test(file)) {
// Transform the .ts file
let fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString();
const info = ts.preProcessFile(fileContents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
const importedFilename = info.importedFiles[i].fileName;
const pos = info.importedFiles[i].pos;
const end = info.importedFiles[i].end;
let importedFilepath: string;
if (/^vs\/css!/.test(importedFilename)) {
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
} else {
importedFilepath = importedFilename;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(file), importedFilepath);
}
let relativePath: string;
if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) {
relativePath = '../' + path.basename(path.dirname(file));
} else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(file)));
} else {
relativePath = path.relative(path.dirname(file), importedFilepath);
}
relativePath = relativePath.replace(/\\/g, '/');
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (
fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1)
);
}
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
return `import * as ${m1} from ${m2};`;
});
write(getDestAbsoluteFilePath(file), fileContents);
continue;
}
console.log(`UNKNOWN FILE: ${file}`);
} }
const esm_opts = {
"compilerOptions": { function walkDirRecursive(dir: string): string[] {
"outDir": path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER), if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') {
"rootDir": "src", dir += '/';
"module": "es6",
"target": "es5",
"experimentalDecorators": true,
"lib": [
"dom",
"es5",
"es2015.collection",
"es2015.promise"
],
"types": [
]
} }
}; let result: string[] = [];
fs.writeFileSync(path.join(path.dirname(OUT_FOLDER), 'tsconfig.json'), JSON.stringify(esm_opts, null, '\t')); _walkDirRecursive(dir, result, dir.length);
return result;
}
const monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString(); function _walkDirRecursive(dir: string, result: string[], trimPos: number): void {
fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts); const files = fs.readdirSync(dir);
for (let i = 0; i < files.length; i++) {
const file = path.join(dir, files[i]);
if (fs.statSync(file).isDirectory()) {
_walkDirRecursive(file, result, trimPos);
} else {
result.push(file.substr(trimPos));
}
}
}
function write(absoluteFilePath: string, contents: string | Buffer): void {
if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) {
contents = toggleComments(contents.toString());
}
writeFile(absoluteFilePath, contents);
function toggleComments(fileContents: string): string {
let lines = fileContents.split(/\r\n|\r|\n/);
let mode = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
}
if (/\/\/ ESM-uncomment-begin/.test(line)) {
mode = 2;
continue;
}
continue;
}
if (mode === 1) {
if (/\/\/ ESM-comment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = '// ' + line;
continue;
}
if (mode === 2) {
if (/\/\/ ESM-uncomment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
}
}
return lines.join('\n');
}
}
} }
function transportCSS(module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean { function transportCSS(module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean {
@@ -337,7 +331,7 @@ function transportCSS(module: string, enqueue: (module: string) => void, write:
function _replaceURL(contents: string, replacer: (url: string) => string): string { function _replaceURL(contents: string, replacer: (url: string) => string): string {
// Use ")" as the terminator as quotes are oftentimes not used at all // Use ")" as the terminator as quotes are oftentimes not used at all
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_: string, ...matches: string[]) => { return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_: string, ...matches: string[]) => {
var url = matches[0]; let url = matches[0];
// Eliminate starting quotes (the initial whitespace is not captured) // Eliminate starting quotes (the initial whitespace is not captured)
if (url.charAt(0) === '"' || url.charAt(0) === '\'') { if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
url = url.substring(1); url = url.substring(1);
@@ -363,33 +357,3 @@ function transportCSS(module: string, enqueue: (module: string) => void, write:
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle; return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
} }
} }
function transportResource(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean {
if (!/\.svg/.test(module)) {
return false;
}
write(module, fs.readFileSync(path.join(SRC_DIR, module)));
return true;
}
function transportDTS(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean {
if (options.redirects[module] && fs.existsSync(path.join(SRC_DIR, options.redirects[module] + '.ts'))) {
return false;
}
if (!fs.existsSync(path.join(SRC_DIR, module + '.d.ts'))) {
return false;
}
write(module + '.d.ts', fs.readFileSync(path.join(SRC_DIR, module + '.d.ts')));
let filename: string;
if (options.redirects[module]) {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, options.redirects[module] + '.js')));
} else {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, module + '.js')));
}
return true;
}

135
build/lib/stats.js Normal file
View File

@@ -0,0 +1,135 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const es = require("event-stream");
const util = require("gulp-util");
const appInsights = require("applicationinsights");
class Entry {
constructor(name, totalCount, totalSize) {
this.name = name;
this.totalCount = totalCount;
this.totalSize = totalSize;
}
toString(pretty) {
if (!pretty) {
if (this.totalCount === 1) {
return `${this.name}: ${this.totalSize} bytes`;
}
else {
return `${this.name}: ${this.totalCount} files with ${this.totalSize} bytes`;
}
}
else {
if (this.totalCount === 1) {
return `Stats for '${util.colors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`;
}
else {
const count = this.totalCount < 100
? util.colors.green(this.totalCount.toString())
: util.colors.red(this.totalCount.toString());
return `Stats for '${util.colors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`;
}
}
}
}
const _entries = new Map();
function createStatsStream(group, log) {
const entry = new Entry(group, 0, 0);
_entries.set(entry.name, entry);
return es.through(function (data) {
const file = data;
if (typeof file.path === 'string') {
entry.totalCount += 1;
if (Buffer.isBuffer(file.contents)) {
entry.totalSize += file.contents.length;
}
else if (file.stat && typeof file.stat.size === 'number') {
entry.totalSize += file.stat.size;
}
else {
// funky file...
}
}
this.emit('data', data);
}, function () {
if (log) {
if (entry.totalCount === 1) {
util.log(`Stats for '${util.colors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`);
}
else {
const count = entry.totalCount < 100
? util.colors.green(entry.totalCount.toString())
: util.colors.red(entry.totalCount.toString());
util.log(`Stats for '${util.colors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`);
}
}
this.emit('end');
});
}
exports.createStatsStream = createStatsStream;
function submitAllStats(productJson, commit) {
const sorted = [];
// move entries for single files to the front
_entries.forEach(value => {
if (value.totalCount === 1) {
sorted.unshift(value);
}
else {
sorted.push(value);
}
});
// print to console
for (const entry of sorted) {
console.log(entry.toString(true));
}
// send data as telementry event when the
// product is configured to send telemetry
if (!productJson || !productJson.aiConfig || typeof productJson.aiConfig.asimovKey !== 'string') {
return Promise.resolve(false);
}
return new Promise(resolve => {
try {
const sizes = {};
const counts = {};
for (const entry of sorted) {
sizes[entry.name] = entry.totalSize;
counts[entry.name] = entry.totalCount;
}
appInsights.setup(productJson.aiConfig.asimovKey)
.setAutoCollectConsole(false)
.setAutoCollectExceptions(false)
.setAutoCollectPerformance(false)
.setAutoCollectRequests(false)
.setAutoCollectDependencies(false)
.setAutoDependencyCorrelation(false)
.start();
appInsights.defaultClient.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
/* __GDPR__
"monacoworkbench/packagemetrics" : {
"commit" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"size" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"count" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
}
*/
appInsights.defaultClient.trackEvent({
name: 'monacoworkbench/packagemetrics',
properties: { commit, size: JSON.stringify(sizes), count: JSON.stringify(counts) }
});
appInsights.defaultClient.flush({
callback: () => {
appInsights.dispose();
resolve(true);
}
});
}
catch (err) {
console.error('ERROR sending build stats as telemetry event!');
console.error(err);
resolve(false);
}
});
}
exports.submitAllStats = submitAllStats;

147
build/lib/stats.ts Normal file
View File

@@ -0,0 +1,147 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as es from 'event-stream';
import * as util from 'gulp-util';
import * as File from 'vinyl';
import * as appInsights from 'applicationinsights';
class Entry {
constructor(readonly name: string, public totalCount: number, public totalSize: number) { }
toString(pretty?: boolean): string {
if (!pretty) {
if (this.totalCount === 1) {
return `${this.name}: ${this.totalSize} bytes`;
} else {
return `${this.name}: ${this.totalCount} files with ${this.totalSize} bytes`;
}
} else {
if (this.totalCount === 1) {
return `Stats for '${util.colors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`;
} else {
const count = this.totalCount < 100
? util.colors.green(this.totalCount.toString())
: util.colors.red(this.totalCount.toString());
return `Stats for '${util.colors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`;
}
}
}
}
const _entries = new Map<string, Entry>();
export function createStatsStream(group: string, log?: boolean): es.ThroughStream {
const entry = new Entry(group, 0, 0);
_entries.set(entry.name, entry);
return es.through(function (data) {
const file = data as File;
if (typeof file.path === 'string') {
entry.totalCount += 1;
if (Buffer.isBuffer(file.contents)) {
entry.totalSize += file.contents.length;
} else if (file.stat && typeof file.stat.size === 'number') {
entry.totalSize += file.stat.size;
} else {
// funky file...
}
}
this.emit('data', data);
}, function () {
if (log) {
if (entry.totalCount === 1) {
util.log(`Stats for '${util.colors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`);
} else {
const count = entry.totalCount < 100
? util.colors.green(entry.totalCount.toString())
: util.colors.red(entry.totalCount.toString());
util.log(`Stats for '${util.colors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`);
}
}
this.emit('end');
});
}
export function submitAllStats(productJson: any, commit: string): Promise<boolean> {
const sorted: Entry[] = [];
// move entries for single files to the front
_entries.forEach(value => {
if (value.totalCount === 1) {
sorted.unshift(value);
} else {
sorted.push(value);
}
});
// print to console
for (const entry of sorted) {
console.log(entry.toString(true));
}
// send data as telementry event when the
// product is configured to send telemetry
if (!productJson || !productJson.aiConfig || typeof productJson.aiConfig.asimovKey !== 'string') {
return Promise.resolve(false);
}
return new Promise(resolve => {
try {
const sizes: any = {};
const counts: any = {};
for (const entry of sorted) {
sizes[entry.name] = entry.totalSize;
counts[entry.name] = entry.totalCount;
}
appInsights.setup(productJson.aiConfig.asimovKey)
.setAutoCollectConsole(false)
.setAutoCollectExceptions(false)
.setAutoCollectPerformance(false)
.setAutoCollectRequests(false)
.setAutoCollectDependencies(false)
.setAutoDependencyCorrelation(false)
.start();
appInsights.defaultClient.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
/* __GDPR__
"monacoworkbench/packagemetrics" : {
"commit" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"size" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"count" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
}
*/
appInsights.defaultClient.trackEvent({
name: 'monacoworkbench/packagemetrics',
properties: { commit, size: JSON.stringify(sizes), count: JSON.stringify(counts) }
});
appInsights.defaultClient.flush({
callback: () => {
appInsights.dispose();
resolve(true);
}
});
} catch (err) {
console.error('ERROR sending build stats as telemetry event!');
console.error(err);
resolve(false);
}
});
}

View File

@@ -4,30 +4,30 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert"); const assert = require("assert");
var i18n = require("../i18n"); const i18n = require("../i18n");
suite('XLF Parser Tests', function () { suite('XLF Parser Tests', () => {
var 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 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>';
var 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 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>';
var originalFilePath = 'vs/base/common/keybinding'; const originalFilePath = 'vs/base/common/keybinding';
var keys = ['key1', 'key2']; const keys = ['key1', 'key2'];
var messages = ['Key #1', 'Key #2 &']; const messages = ['Key #1', 'Key #2 &'];
var translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' }; const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' };
test('Keys & messages to XLF conversion', function () { test('Keys & messages to XLF conversion', () => {
var xlf = new i18n.XLF('vscode-workbench'); const xlf = new i18n.XLF('vscode-workbench');
xlf.addFile(originalFilePath, keys, messages); xlf.addFile(originalFilePath, keys, messages);
var xlfString = xlf.toString(); const xlfString = xlf.toString();
assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf); assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf);
}); });
test('XLF to keys & messages conversion', function () { test('XLF to keys & messages conversion', () => {
i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) { i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) {
assert.deepEqual(resolvedFiles[0].messages, translatedMessages); assert.deepEqual(resolvedFiles[0].messages, translatedMessages);
assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath); assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath);
}); });
}); });
test('JSON file source path to Transifex resource match', function () { test('JSON file source path to Transifex resource match', () => {
var editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench'; const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench';
var platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/parts/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/files', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject }; const platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/parts/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/files', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject };
assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform); assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform);
assert.deepEqual(i18n.getResource('vs/editor/contrib/clipboard/browser/clipboard'), editorContrib); assert.deepEqual(i18n.getResource('vs/editor/contrib/clipboard/browser/clipboard'), editorContrib);
assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor); assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor);

View File

@@ -15,7 +15,7 @@ suite('XLF Parser Tests', () => {
const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' }; const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' };
test('Keys & messages to XLF conversion', () => { test('Keys & messages to XLF conversion', () => {
let xlf = new i18n.XLF('vscode-workbench'); const xlf = new i18n.XLF('vscode-workbench');
xlf.addFile(originalFilePath, keys, messages); xlf.addFile(originalFilePath, keys, messages);
const xlfString = xlf.toString(); const xlfString = xlf.toString();

View File

@@ -4,18 +4,49 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var ts = require("typescript"); const ts = require("typescript");
var TYPESCRIPT_LIB_FOLDER = path.dirname(require.resolve('typescript/lib/lib.d.ts')); const TYPESCRIPT_LIB_FOLDER = path.dirname(require.resolve('typescript/lib/lib.d.ts'));
var ShakeLevel; var ShakeLevel;
(function (ShakeLevel) { (function (ShakeLevel) {
ShakeLevel[ShakeLevel["Files"] = 0] = "Files"; ShakeLevel[ShakeLevel["Files"] = 0] = "Files";
ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile"; ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile";
ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers"; ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers";
})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {})); })(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {}));
function printDiagnostics(diagnostics) {
for (let i = 0; i < diagnostics.length; i++) {
const diag = diagnostics[i];
let result = '';
if (diag.file) {
result += `${diag.file.fileName}: `;
}
if (diag.file && diag.start) {
let location = diag.file.getLineAndCharacterOfPosition(diag.start);
result += `- ${location.line + 1},${location.character} - `;
}
result += JSON.stringify(diag.messageText);
console.log(result);
}
}
function shake(options) { function shake(options) {
var languageService = createTypeScriptLanguageService(options); const languageService = createTypeScriptLanguageService(options);
const program = languageService.getProgram();
const globalDiagnostics = program.getGlobalDiagnostics();
if (globalDiagnostics.length > 0) {
printDiagnostics(globalDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
const syntacticDiagnostics = program.getSyntacticDiagnostics();
if (syntacticDiagnostics.length > 0) {
printDiagnostics(syntacticDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
const semanticDiagnostics = program.getSemanticDiagnostics();
if (semanticDiagnostics.length > 0) {
printDiagnostics(semanticDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
markNodes(languageService, options); markNodes(languageService, options);
return generateResult(languageService, options.shakeLevel); return generateResult(languageService, options.shakeLevel);
} }
@@ -23,93 +54,99 @@ exports.shake = shake;
//#region Discovery, LanguageService & Setup //#region Discovery, LanguageService & Setup
function createTypeScriptLanguageService(options) { function createTypeScriptLanguageService(options) {
// Discover referenced files // Discover referenced files
var FILES = discoverAndReadFiles(options); const FILES = discoverAndReadFiles(options);
// Add fake usage files // Add fake usage files
options.inlineEntryPoints.forEach(function (inlineEntryPoint, index) { options.inlineEntryPoints.forEach((inlineEntryPoint, index) => {
FILES["inlineEntryPoint:" + index + ".ts"] = inlineEntryPoint; FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint;
});
// Add additional typings
options.typings.forEach((typing) => {
const filePath = path.join(options.sourcesRoot, typing);
FILES[typing] = fs.readFileSync(filePath).toString();
}); });
// Resolve libs // Resolve libs
var RESOLVED_LIBS = {}; const RESOLVED_LIBS = {};
options.libs.forEach(function (filename) { options.libs.forEach((filename) => {
var filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename); const filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename);
RESOLVED_LIBS["defaultLib:" + filename] = fs.readFileSync(filepath).toString(); RESOLVED_LIBS[`defaultLib:${filename}`] = fs.readFileSync(filepath).toString();
}); });
var host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, options.compilerOptions); const compilerOptions = ts.convertCompilerOptionsFromJson(options.compilerOptions, options.sourcesRoot).options;
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, compilerOptions);
return ts.createLanguageService(host); return ts.createLanguageService(host);
} }
/** /**
* Read imports and follow them until all files have been handled * Read imports and follow them until all files have been handled
*/ */
function discoverAndReadFiles(options) { function discoverAndReadFiles(options) {
var FILES = {}; const FILES = {};
var in_queue = Object.create(null); const in_queue = Object.create(null);
var queue = []; const queue = [];
var enqueue = function (moduleId) { const enqueue = (moduleId) => {
if (in_queue[moduleId]) { if (in_queue[moduleId]) {
return; return;
} }
in_queue[moduleId] = true; in_queue[moduleId] = true;
queue.push(moduleId); queue.push(moduleId);
}; };
options.entryPoints.forEach(function (entryPoint) { return enqueue(entryPoint); }); options.entryPoints.forEach((entryPoint) => enqueue(entryPoint));
while (queue.length > 0) { while (queue.length > 0) {
var moduleId = queue.shift(); const moduleId = queue.shift();
var dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts'); const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts');
if (fs.existsSync(dts_filename)) { if (fs.existsSync(dts_filename)) {
var dts_filecontents = fs.readFileSync(dts_filename).toString(); const dts_filecontents = fs.readFileSync(dts_filename).toString();
FILES[moduleId + '.d.ts'] = dts_filecontents; FILES[`${moduleId}.d.ts`] = dts_filecontents;
continue; continue;
} }
var ts_filename = void 0; let ts_filename;
if (options.redirects[moduleId]) { if (options.redirects[moduleId]) {
ts_filename = path.join(options.sourcesRoot, options.redirects[moduleId] + '.ts'); ts_filename = path.join(options.sourcesRoot, options.redirects[moduleId] + '.ts');
} }
else { else {
ts_filename = path.join(options.sourcesRoot, moduleId + '.ts'); ts_filename = path.join(options.sourcesRoot, moduleId + '.ts');
} }
var ts_filecontents = fs.readFileSync(ts_filename).toString(); const ts_filecontents = fs.readFileSync(ts_filename).toString();
var info = ts.preProcessFile(ts_filecontents); const info = ts.preProcessFile(ts_filecontents);
for (var i = info.importedFiles.length - 1; i >= 0; i--) { for (let i = info.importedFiles.length - 1; i >= 0; i--) {
var importedFileName = info.importedFiles[i].fileName; const importedFileName = info.importedFiles[i].fileName;
if (options.importIgnorePattern.test(importedFileName)) { if (options.importIgnorePattern.test(importedFileName)) {
// Ignore vs/css! imports // Ignore vs/css! imports
continue; continue;
} }
var importedModuleId = importedFileName; let importedModuleId = importedFileName;
if (/(^\.\/)|(^\.\.\/)/.test(importedModuleId)) { if (/(^\.\/)|(^\.\.\/)/.test(importedModuleId)) {
importedModuleId = path.join(path.dirname(moduleId), importedModuleId); importedModuleId = path.join(path.dirname(moduleId), importedModuleId);
} }
enqueue(importedModuleId); enqueue(importedModuleId);
} }
FILES[moduleId + '.ts'] = ts_filecontents; FILES[`${moduleId}.ts`] = ts_filecontents;
} }
return FILES; return FILES;
} }
/** /**
* A TypeScript language service host * A TypeScript language service host
*/ */
var TypeScriptLanguageServiceHost = /** @class */ (function () { class TypeScriptLanguageServiceHost {
function TypeScriptLanguageServiceHost(libs, files, compilerOptions) { constructor(libs, files, compilerOptions) {
this._libs = libs; this._libs = libs;
this._files = files; this._files = files;
this._compilerOptions = compilerOptions; this._compilerOptions = compilerOptions;
} }
// --- language service host --------------- // --- language service host ---------------
TypeScriptLanguageServiceHost.prototype.getCompilationSettings = function () { getCompilationSettings() {
return this._compilerOptions; return this._compilerOptions;
}; }
TypeScriptLanguageServiceHost.prototype.getScriptFileNames = function () { getScriptFileNames() {
return ([] return ([]
.concat(Object.keys(this._libs)) .concat(Object.keys(this._libs))
.concat(Object.keys(this._files))); .concat(Object.keys(this._files)));
}; }
TypeScriptLanguageServiceHost.prototype.getScriptVersion = function (fileName) { getScriptVersion(_fileName) {
return '1'; return '1';
}; }
TypeScriptLanguageServiceHost.prototype.getProjectVersion = function () { getProjectVersion() {
return '1'; return '1';
}; }
TypeScriptLanguageServiceHost.prototype.getScriptSnapshot = function (fileName) { getScriptSnapshot(fileName) {
if (this._files.hasOwnProperty(fileName)) { if (this._files.hasOwnProperty(fileName)) {
return ts.ScriptSnapshot.fromString(this._files[fileName]); return ts.ScriptSnapshot.fromString(this._files[fileName]);
} }
@@ -119,21 +156,20 @@ var TypeScriptLanguageServiceHost = /** @class */ (function () {
else { else {
return ts.ScriptSnapshot.fromString(''); return ts.ScriptSnapshot.fromString('');
} }
}; }
TypeScriptLanguageServiceHost.prototype.getScriptKind = function (fileName) { getScriptKind(_fileName) {
return ts.ScriptKind.TS; return ts.ScriptKind.TS;
}; }
TypeScriptLanguageServiceHost.prototype.getCurrentDirectory = function () { getCurrentDirectory() {
return ''; return '';
}; }
TypeScriptLanguageServiceHost.prototype.getDefaultLibFileName = function (options) { getDefaultLibFileName(_options) {
return 'defaultLib:lib.d.ts'; return 'defaultLib:lib.d.ts';
}; }
TypeScriptLanguageServiceHost.prototype.isDefaultLibFileName = function (fileName) { isDefaultLibFileName(fileName) {
return fileName === this.getDefaultLibFileName(this._compilerOptions); return fileName === this.getDefaultLibFileName(this._compilerOptions);
}; }
return TypeScriptLanguageServiceHost; }
}());
//#endregion //#endregion
//#region Tree Shaking //#region Tree Shaking
var NodeColor; var NodeColor;
@@ -150,7 +186,7 @@ function setColor(node, color) {
} }
function nodeOrParentIsBlack(node) { function nodeOrParentIsBlack(node) {
while (node) { while (node) {
var color = getColor(node); const color = getColor(node);
if (color === 2 /* Black */) { if (color === 2 /* Black */) {
return true; return true;
} }
@@ -162,8 +198,7 @@ function nodeOrChildIsBlack(node) {
if (getColor(node) === 2 /* Black */) { if (getColor(node) === 2 /* Black */) {
return true; return true;
} }
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) { for (const child of node.getChildren()) {
var child = _a[_i];
if (nodeOrChildIsBlack(child)) { if (nodeOrChildIsBlack(child)) {
return true; return true;
} }
@@ -171,19 +206,22 @@ function nodeOrChildIsBlack(node) {
return false; return false;
} }
function markNodes(languageService, options) { function markNodes(languageService, options) {
var program = languageService.getProgram(); const program = languageService.getProgram();
if (!program) {
throw new Error('Could not get program from language service');
}
if (options.shakeLevel === 0 /* Files */) { if (options.shakeLevel === 0 /* Files */) {
// Mark all source files Black // Mark all source files Black
program.getSourceFiles().forEach(function (sourceFile) { program.getSourceFiles().forEach((sourceFile) => {
setColor(sourceFile, 2 /* Black */); setColor(sourceFile, 2 /* Black */);
}); });
return; return;
} }
var black_queue = []; const black_queue = [];
var gray_queue = []; const gray_queue = [];
var sourceFilesLoaded = {}; const sourceFilesLoaded = {};
function enqueueTopLevelModuleStatements(sourceFile) { function enqueueTopLevelModuleStatements(sourceFile) {
sourceFile.forEachChild(function (node) { sourceFile.forEachChild((node) => {
if (ts.isImportDeclaration(node)) { if (ts.isImportDeclaration(node)) {
if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) { if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) {
setColor(node, 2 /* Black */); setColor(node, 2 /* Black */);
@@ -192,7 +230,7 @@ function markNodes(languageService, options) {
return; return;
} }
if (ts.isExportDeclaration(node)) { if (ts.isExportDeclaration(node)) {
if (ts.isStringLiteral(node.moduleSpecifier)) { if (node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
setColor(node, 2 /* Black */); setColor(node, 2 /* Black */);
enqueueImport(node, node.moduleSpecifier.text); enqueueImport(node, node.moduleSpecifier.text);
} }
@@ -220,7 +258,7 @@ function markNodes(languageService, options) {
gray_queue.push(node); gray_queue.push(node);
} }
function enqueue_black(node) { function enqueue_black(node) {
var previousColor = getColor(node); const previousColor = getColor(node);
if (previousColor === 2 /* Black */) { if (previousColor === 2 /* Black */) {
return; return;
} }
@@ -238,12 +276,12 @@ function markNodes(languageService, options) {
if (nodeOrParentIsBlack(node)) { if (nodeOrParentIsBlack(node)) {
return; return;
} }
var fileName = node.getSourceFile().fileName; const fileName = node.getSourceFile().fileName;
if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) { if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) {
setColor(node, 2 /* Black */); setColor(node, 2 /* Black */);
return; return;
} }
var sourceFile = node.getSourceFile(); const sourceFile = node.getSourceFile();
if (!sourceFilesLoaded[sourceFile.fileName]) { if (!sourceFilesLoaded[sourceFile.fileName]) {
sourceFilesLoaded[sourceFile.fileName] = true; sourceFilesLoaded[sourceFile.fileName] = true;
enqueueTopLevelModuleStatements(sourceFile); enqueueTopLevelModuleStatements(sourceFile);
@@ -254,12 +292,15 @@ function markNodes(languageService, options) {
setColor(node, 2 /* Black */); setColor(node, 2 /* Black */);
black_queue.push(node); black_queue.push(node);
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) { if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) {
var references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth()); const references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth());
if (references) { if (references) {
for (var i = 0, len = references.length; i < len; i++) { for (let i = 0, len = references.length; i < len; i++) {
var reference = references[i]; const reference = references[i];
var referenceSourceFile = program.getSourceFile(reference.fileName); const referenceSourceFile = program.getSourceFile(reference.fileName);
var referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false); if (!referenceSourceFile) {
continue;
}
const referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false);
if (ts.isMethodDeclaration(referenceNode.parent) if (ts.isMethodDeclaration(referenceNode.parent)
|| ts.isPropertyDeclaration(referenceNode.parent) || ts.isPropertyDeclaration(referenceNode.parent)
|| ts.isGetAccessor(referenceNode.parent) || ts.isGetAccessor(referenceNode.parent)
@@ -271,9 +312,9 @@ function markNodes(languageService, options) {
} }
} }
function enqueueFile(filename) { function enqueueFile(filename) {
var sourceFile = program.getSourceFile(filename); const sourceFile = program.getSourceFile(filename);
if (!sourceFile) { if (!sourceFile) {
console.warn("Cannot find source file " + filename); console.warn(`Cannot find source file ${filename}`);
return; return;
} }
enqueue_black(sourceFile); enqueue_black(sourceFile);
@@ -283,8 +324,8 @@ function markNodes(languageService, options) {
// this import should be ignored // this import should be ignored
return; return;
} }
var nodeSourceFile = node.getSourceFile(); const nodeSourceFile = node.getSourceFile();
var fullPath; let fullPath;
if (/(^\.\/)|(^\.\.\/)/.test(importText)) { if (/(^\.\/)|(^\.\.\/)/.test(importText)) {
fullPath = path.join(path.dirname(nodeSourceFile.fileName), importText) + '.ts'; fullPath = path.join(path.dirname(nodeSourceFile.fileName), importText) + '.ts';
} }
@@ -293,25 +334,25 @@ function markNodes(languageService, options) {
} }
enqueueFile(fullPath); enqueueFile(fullPath);
} }
options.entryPoints.forEach(function (moduleId) { return enqueueFile(moduleId + '.ts'); }); options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts'));
// Add fake usage files // Add fake usage files
options.inlineEntryPoints.forEach(function (_, index) { return enqueueFile("inlineEntryPoint:" + index + ".ts"); }); options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`));
var step = 0; let step = 0;
var checker = program.getTypeChecker(); const checker = program.getTypeChecker();
var _loop_1 = function () { while (black_queue.length > 0 || gray_queue.length > 0) {
++step; ++step;
var node = void 0; let node;
if (step % 100 === 0) { if (step % 100 === 0) {
console.log(step + "/" + (step + black_queue.length + gray_queue.length) + " (" + black_queue.length + ", " + gray_queue.length + ")"); console.log(`${step}/${step + black_queue.length + gray_queue.length} (${black_queue.length}, ${gray_queue.length})`);
} }
if (black_queue.length === 0) { if (black_queue.length === 0) {
for (var i = 0; i < gray_queue.length; i++) { for (let i = 0; i < gray_queue.length; i++) {
var node_1 = gray_queue[i]; const node = gray_queue[i];
var nodeParent = node_1.parent; const nodeParent = node.parent;
if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) { if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) {
gray_queue.splice(i, 1); gray_queue.splice(i, 1);
black_queue.push(node_1); black_queue.push(node);
setColor(node_1, 2 /* Black */); setColor(node, 2 /* Black */);
i--; i--;
} }
} }
@@ -320,17 +361,18 @@ function markNodes(languageService, options) {
node = black_queue.shift(); node = black_queue.shift();
} }
else { else {
return "break"; // only gray nodes remaining...
break;
} }
var nodeSourceFile = node.getSourceFile(); const nodeSourceFile = node.getSourceFile();
var loop = function (node) { const loop = (node) => {
var _a = getRealNodeSymbol(checker, node), symbol = _a[0], symbolImportNode = _a[1]; const [symbol, symbolImportNode] = getRealNodeSymbol(checker, node);
if (symbolImportNode) { if (symbolImportNode) {
setColor(symbolImportNode, 2 /* Black */); setColor(symbolImportNode, 2 /* Black */);
} }
if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) { if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
for (var i = 0, len = symbol.declarations.length; i < len; i++) { for (let i = 0, len = symbol.declarations.length; i < len; i++) {
var declaration = symbol.declarations[i]; const declaration = symbol.declarations[i];
if (ts.isSourceFile(declaration)) { if (ts.isSourceFile(declaration)) {
// Do not enqueue full source files // Do not enqueue full source files
// (they can be the declaration of a module import) // (they can be the declaration of a module import)
@@ -338,9 +380,9 @@ function markNodes(languageService, options) {
} }
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration))) { if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration))) {
enqueue_black(declaration.name); enqueue_black(declaration.name);
for (var j = 0; j < declaration.members.length; j++) { for (let j = 0; j < declaration.members.length; j++) {
var member = declaration.members[j]; const member = declaration.members[j];
var memberName = member.name ? member.name.getText() : null; const memberName = member.name ? member.name.getText() : null;
if (ts.isConstructorDeclaration(member) if (ts.isConstructorDeclaration(member)
|| ts.isConstructSignatureDeclaration(member) || ts.isConstructSignatureDeclaration(member)
|| ts.isIndexSignatureDeclaration(member) || ts.isIndexSignatureDeclaration(member)
@@ -354,8 +396,7 @@ function markNodes(languageService, options) {
} }
// queue the heritage clauses // queue the heritage clauses
if (declaration.heritageClauses) { if (declaration.heritageClauses) {
for (var _i = 0, _b = declaration.heritageClauses; _i < _b.length; _i++) { for (let heritageClause of declaration.heritageClauses) {
var heritageClause = _b[_i];
enqueue_black(heritageClause); enqueue_black(heritageClause);
} }
} }
@@ -368,17 +409,12 @@ function markNodes(languageService, options) {
node.forEachChild(loop); node.forEachChild(loop);
}; };
node.forEachChild(loop); node.forEachChild(loop);
};
while (black_queue.length > 0 || gray_queue.length > 0) {
var state_1 = _loop_1();
if (state_1 === "break")
break;
} }
} }
function nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol) { function nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol) {
for (var i = 0, len = symbol.declarations.length; i < len; i++) { for (let i = 0, len = symbol.declarations.length; i < len; i++) {
var declaration = symbol.declarations[i]; const declaration = symbol.declarations[i];
var declarationSourceFile = declaration.getSourceFile(); const declarationSourceFile = declaration.getSourceFile();
if (nodeSourceFile === declarationSourceFile) { if (nodeSourceFile === declarationSourceFile) {
if (declaration.pos <= node.pos && node.end <= declaration.end) { if (declaration.pos <= node.pos && node.end <= declaration.end) {
return true; return true;
@@ -388,25 +424,28 @@ function nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol) {
return false; return false;
} }
function generateResult(languageService, shakeLevel) { function generateResult(languageService, shakeLevel) {
var program = languageService.getProgram(); const program = languageService.getProgram();
var result = {}; if (!program) {
var writeFile = function (filePath, contents) { throw new Error('Could not get program from language service');
}
let result = {};
const writeFile = (filePath, contents) => {
result[filePath] = contents; result[filePath] = contents;
}; };
program.getSourceFiles().forEach(function (sourceFile) { program.getSourceFiles().forEach((sourceFile) => {
var fileName = sourceFile.fileName; const fileName = sourceFile.fileName;
if (/^defaultLib:/.test(fileName)) { if (/^defaultLib:/.test(fileName)) {
return; return;
} }
var destination = fileName; const destination = fileName;
if (/\.d\.ts$/.test(fileName)) { if (/\.d\.ts$/.test(fileName)) {
if (nodeOrChildIsBlack(sourceFile)) { if (nodeOrChildIsBlack(sourceFile)) {
writeFile(destination, sourceFile.text); writeFile(destination, sourceFile.text);
} }
return; return;
} }
var text = sourceFile.text; let text = sourceFile.text;
var result = ''; let result = '';
function keep(node) { function keep(node) {
result += text.substring(node.pos, node.end); result += text.substring(node.pos, node.end);
} }
@@ -435,24 +474,24 @@ function generateResult(languageService, shakeLevel) {
} }
} }
else { else {
var survivingImports = []; let survivingImports = [];
for (var i = 0; i < node.importClause.namedBindings.elements.length; i++) { for (let i = 0; i < node.importClause.namedBindings.elements.length; i++) {
var importNode = node.importClause.namedBindings.elements[i]; const importNode = node.importClause.namedBindings.elements[i];
if (getColor(importNode) === 2 /* Black */) { if (getColor(importNode) === 2 /* Black */) {
survivingImports.push(importNode.getFullText(sourceFile)); survivingImports.push(importNode.getFullText(sourceFile));
} }
} }
var leadingTriviaWidth = node.getLeadingTriviaWidth(); const leadingTriviaWidth = node.getLeadingTriviaWidth();
var leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth); const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
if (survivingImports.length > 0) { if (survivingImports.length > 0) {
if (node.importClause && getColor(node.importClause) === 2 /* Black */) { if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
return write(leadingTrivia + "import " + node.importClause.name.text + ", {" + survivingImports.join(',') + " } from" + node.moduleSpecifier.getFullText(sourceFile) + ";"); return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
} }
return write(leadingTrivia + "import {" + survivingImports.join(',') + " } from" + node.moduleSpecifier.getFullText(sourceFile) + ";"); return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
} }
else { else {
if (node.importClause && getColor(node.importClause) === 2 /* Black */) { if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
return write(leadingTrivia + "import " + node.importClause.name.text + " from" + node.moduleSpecifier.getFullText(sourceFile) + ";"); return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`);
} }
} }
} }
@@ -464,10 +503,10 @@ function generateResult(languageService, shakeLevel) {
} }
} }
if (shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) { if (shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) {
var toWrite = node.getFullText(); let toWrite = node.getFullText();
for (var i = node.members.length - 1; i >= 0; i--) { for (let i = node.members.length - 1; i >= 0; i--) {
var member = node.members[i]; const member = node.members[i];
if (getColor(member) === 2 /* Black */) { if (getColor(member) === 2 /* Black */ || !member.name) {
// keep method // keep method
continue; continue;
} }
@@ -475,8 +514,8 @@ function generateResult(languageService, shakeLevel) {
// TODO: keep all members ending with `Brand`... // TODO: keep all members ending with `Brand`...
continue; continue;
} }
var pos = member.pos - node.pos; let pos = member.pos - node.pos;
var end = member.end - node.pos; let end = member.end - node.pos;
toWrite = toWrite.substring(0, pos) + toWrite.substring(end); toWrite = toWrite.substring(0, pos) + toWrite.substring(end);
} }
return write(toWrite); return write(toWrite);
@@ -508,68 +547,9 @@ function generateResult(languageService, shakeLevel) {
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module) * Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
*/ */
function getRealNodeSymbol(checker, node) { function getRealNodeSymbol(checker, node) {
/** const getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType;
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } const getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement;
*/ const getNameFromPropertyName = ts.getNameFromPropertyName;
/* @internal */
function getContainingObjectLiteralElement(node) {
switch (node.kind) {
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.NumericLiteral:
if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) {
return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
}
// falls through
case ts.SyntaxKind.Identifier:
return ts.isObjectLiteralElement(node.parent) &&
(node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) &&
node.parent.name === node ? node.parent : undefined;
}
return undefined;
}
function getPropertySymbolsFromType(type, propName) {
function getTextOfPropertyName(name) {
function isStringOrNumericLiteral(node) {
var kind = node.kind;
return kind === ts.SyntaxKind.StringLiteral
|| kind === ts.SyntaxKind.NumericLiteral;
}
switch (name.kind) {
case ts.SyntaxKind.Identifier:
return name.text;
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.NumericLiteral:
return name.text;
case ts.SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined;
}
}
var name = getTextOfPropertyName(propName);
if (name && type) {
var result = [];
var symbol_1 = type.getProperty(name);
if (type.flags & ts.TypeFlags.Union) {
for (var _i = 0, _a = type.types; _i < _a.length; _i++) {
var t = _a[_i];
var symbol_2 = t.getProperty(name);
if (symbol_2) {
result.push(symbol_2);
}
}
return result;
}
if (symbol_1) {
result.push(symbol_1);
return result;
}
}
return undefined;
}
function getPropertySymbolsFromContextualType(typeChecker, node) {
var objectLiteral = node.parent;
var contextualType = typeChecker.getContextualType(objectLiteral);
return getPropertySymbolsFromType(contextualType, node.name);
}
// Go to the original declaration for cases: // Go to the original declaration for cases:
// //
// (1) when the aliased symbol was declared in the location(parent). // (1) when the aliased symbol was declared in the location(parent).
@@ -597,10 +577,15 @@ function getRealNodeSymbol(checker, node) {
return [null, null]; return [null, null];
} }
} }
var symbol = checker.getSymbolAtLocation(node); const { parent } = node;
var importNode = null; let symbol = checker.getSymbolAtLocation(node);
let importNode = null;
// If this is an alias, and the request came at the declaration location
// get the aliased symbol instead. This allows for goto def on an import e.g.
// import {A, B} from "mod";
// to jump to the implementation directly.
if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
var aliased = checker.getAliasedSymbol(symbol); const aliased = checker.getAliasedSymbol(symbol);
if (aliased.declarations) { if (aliased.declarations) {
// We should mark the import as visited // We should mark the import as visited
importNode = symbol.declarations[0]; importNode = symbol.declarations[0];
@@ -627,13 +612,22 @@ function getRealNodeSymbol(checker, node) {
// pr/*destination*/op1: number // pr/*destination*/op1: number
// } // }
// bar<Test>(({pr/*goto*/op1})=>{}); // bar<Test>(({pr/*goto*/op1})=>{});
if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) && if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
(node === (node.parent.propertyName || node.parent.name))) { (node === (parent.propertyName || parent.name))) {
var type = checker.getTypeAtLocation(node.parent.parent); const name = getNameFromPropertyName(node);
if (type) { const type = checker.getTypeAtLocation(parent.parent);
var propSymbols = getPropertySymbolsFromType(type, node); if (name && type) {
if (propSymbols) { if (type.isUnion()) {
symbol = propSymbols[0]; const prop = type.types[0].getProperty(name);
if (prop) {
symbol = prop;
}
}
else {
const prop = type.getProperty(name);
if (prop) {
symbol = prop;
}
} }
} }
} }
@@ -646,11 +640,14 @@ function getRealNodeSymbol(checker, node) {
// } // }
// function Foo(arg: Props) {} // function Foo(arg: Props) {}
// Foo( { pr/*1*/op1: 10, prop2: false }) // Foo( { pr/*1*/op1: 10, prop2: false })
var element = getContainingObjectLiteralElement(node); const element = getContainingObjectLiteralElement(node);
if (element && checker.getContextualType(element.parent)) { if (element) {
var propertySymbols = getPropertySymbolsFromContextualType(checker, element); const contextualType = element && checker.getContextualType(element.parent);
if (propertySymbols) { if (contextualType) {
symbol = propertySymbols[0]; const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
if (propertySymbols) {
symbol = propertySymbols[0];
}
} }
} }
} }
@@ -661,17 +658,16 @@ function getRealNodeSymbol(checker, node) {
} }
/** Get the token whose text contains the position */ /** Get the token whose text contains the position */
function getTokenAtPosition(sourceFile, position, allowPositionInLeadingTrivia, includeEndPosition) { function getTokenAtPosition(sourceFile, position, allowPositionInLeadingTrivia, includeEndPosition) {
var current = sourceFile; let current = sourceFile;
outer: while (true) { outer: while (true) {
// find the child that contains 'position' // find the child that contains 'position'
for (var _i = 0, _a = current.getChildren(); _i < _a.length; _i++) { for (const child of current.getChildren()) {
var child = _a[_i]; const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, /*includeJsDoc*/ true);
var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, /*includeJsDoc*/ true);
if (start > position) { if (start > position) {
// If this child begins after position, then all subsequent children will as well. // If this child begins after position, then all subsequent children will as well.
break; break;
} }
var end = child.getEnd(); const end = child.getEnd();
if (position < end || (position === end && (child.kind === ts.SyntaxKind.EndOfFileToken || includeEndPosition))) { if (position < end || (position === end && (child.kind === ts.SyntaxKind.EndOfFileToken || includeEndPosition))) {
current = child; current = child;
continue outer; continue outer;

View File

@@ -36,10 +36,14 @@ export interface ITreeShakingOptions {
* e.g. `lib.d.ts`, `lib.es2015.collection.d.ts` * e.g. `lib.d.ts`, `lib.es2015.collection.d.ts`
*/ */
libs: string[]; libs: string[];
/**
* Other .d.ts files
*/
typings: string[];
/** /**
* TypeScript compiler options. * TypeScript compiler options.
*/ */
compilerOptions: ts.CompilerOptions; compilerOptions?: any;
/** /**
* The shake level to perform. * The shake level to perform.
*/ */
@@ -56,8 +60,43 @@ export interface ITreeShakingResult {
[file: string]: string; [file: string]: string;
} }
function printDiagnostics(diagnostics: ReadonlyArray<ts.Diagnostic>): void {
for (let i = 0; i < diagnostics.length; i++) {
const diag = diagnostics[i];
let result = '';
if (diag.file) {
result += `${diag.file.fileName}: `;
}
if (diag.file && diag.start) {
let location = diag.file.getLineAndCharacterOfPosition(diag.start);
result += `- ${location.line + 1},${location.character} - `
}
result += JSON.stringify(diag.messageText);
console.log(result);
}
}
export function shake(options: ITreeShakingOptions): ITreeShakingResult { export function shake(options: ITreeShakingOptions): ITreeShakingResult {
const languageService = createTypeScriptLanguageService(options); const languageService = createTypeScriptLanguageService(options);
const program = languageService.getProgram()!;
const globalDiagnostics = program.getGlobalDiagnostics();
if (globalDiagnostics.length > 0) {
printDiagnostics(globalDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
const syntacticDiagnostics = program.getSyntacticDiagnostics();
if (syntacticDiagnostics.length > 0) {
printDiagnostics(syntacticDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
const semanticDiagnostics = program.getSemanticDiagnostics();
if (semanticDiagnostics.length > 0) {
printDiagnostics(semanticDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
markNodes(languageService, options); markNodes(languageService, options);
@@ -71,7 +110,13 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu
// Add fake usage files // Add fake usage files
options.inlineEntryPoints.forEach((inlineEntryPoint, index) => { options.inlineEntryPoints.forEach((inlineEntryPoint, index) => {
FILES[`inlineEntryPoint:${index}.ts`] = inlineEntryPoint; FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint;
});
// Add additional typings
options.typings.forEach((typing) => {
const filePath = path.join(options.sourcesRoot, typing);
FILES[typing] = fs.readFileSync(filePath).toString();
}); });
// Resolve libs // Resolve libs
@@ -81,7 +126,9 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu
RESOLVED_LIBS[`defaultLib:${filename}`] = fs.readFileSync(filepath).toString(); RESOLVED_LIBS[`defaultLib:${filename}`] = fs.readFileSync(filepath).toString();
}); });
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, options.compilerOptions); const compilerOptions = ts.convertCompilerOptionsFromJson(options.compilerOptions, options.sourcesRoot).options;
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, compilerOptions);
return ts.createLanguageService(host); return ts.createLanguageService(host);
} }
@@ -105,11 +152,11 @@ function discoverAndReadFiles(options: ITreeShakingOptions): IFileMap {
options.entryPoints.forEach((entryPoint) => enqueue(entryPoint)); options.entryPoints.forEach((entryPoint) => enqueue(entryPoint));
while (queue.length > 0) { while (queue.length > 0) {
const moduleId = queue.shift(); const moduleId = queue.shift()!;
const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts'); const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts');
if (fs.existsSync(dts_filename)) { if (fs.existsSync(dts_filename)) {
const dts_filecontents = fs.readFileSync(dts_filename).toString(); const dts_filecontents = fs.readFileSync(dts_filename).toString();
FILES[moduleId + '.d.ts'] = dts_filecontents; FILES[`${moduleId}.d.ts`] = dts_filecontents;
continue; continue;
} }
@@ -136,7 +183,7 @@ function discoverAndReadFiles(options: ITreeShakingOptions): IFileMap {
enqueue(importedModuleId); enqueue(importedModuleId);
} }
FILES[moduleId + '.ts'] = ts_filecontents; FILES[`${moduleId}.ts`] = ts_filecontents;
} }
return FILES; return FILES;
@@ -167,12 +214,12 @@ class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost {
} }
getScriptFileNames(): string[] { getScriptFileNames(): string[] {
return ( return (
[] ([] as string[])
.concat(Object.keys(this._libs)) .concat(Object.keys(this._libs))
.concat(Object.keys(this._files)) .concat(Object.keys(this._files))
); );
} }
getScriptVersion(fileName: string): string { getScriptVersion(_fileName: string): string {
return '1'; return '1';
} }
getProjectVersion(): string { getProjectVersion(): string {
@@ -187,13 +234,13 @@ class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost {
return ts.ScriptSnapshot.fromString(''); return ts.ScriptSnapshot.fromString('');
} }
} }
getScriptKind(fileName: string): ts.ScriptKind { getScriptKind(_fileName: string): ts.ScriptKind {
return ts.ScriptKind.TS; return ts.ScriptKind.TS;
} }
getCurrentDirectory(): string { getCurrentDirectory(): string {
return ''; return '';
} }
getDefaultLibFileName(options: ts.CompilerOptions): string { getDefaultLibFileName(_options: ts.CompilerOptions): string {
return 'defaultLib:lib.d.ts'; return 'defaultLib:lib.d.ts';
} }
isDefaultLibFileName(fileName: string): boolean { isDefaultLibFileName(fileName: string): boolean {
@@ -240,6 +287,9 @@ function nodeOrChildIsBlack(node: ts.Node): boolean {
function markNodes(languageService: ts.LanguageService, options: ITreeShakingOptions) { function markNodes(languageService: ts.LanguageService, options: ITreeShakingOptions) {
const program = languageService.getProgram(); const program = languageService.getProgram();
if (!program) {
throw new Error('Could not get program from language service');
}
if (options.shakeLevel === ShakeLevel.Files) { if (options.shakeLevel === ShakeLevel.Files) {
// Mark all source files Black // Mark all source files Black
@@ -266,7 +316,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
} }
if (ts.isExportDeclaration(node)) { if (ts.isExportDeclaration(node)) {
if (ts.isStringLiteral(node.moduleSpecifier)) { if (node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
setColor(node, NodeColor.Black); setColor(node, NodeColor.Black);
enqueueImport(node, node.moduleSpecifier.text); enqueueImport(node, node.moduleSpecifier.text);
} }
@@ -349,7 +399,11 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
if (references) { if (references) {
for (let i = 0, len = references.length; i < len; i++) { for (let i = 0, len = references.length; i < len; i++) {
const reference = references[i]; const reference = references[i];
const referenceSourceFile = program.getSourceFile(reference.fileName); const referenceSourceFile = program!.getSourceFile(reference.fileName);
if (!referenceSourceFile) {
continue;
}
const referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false); const referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false);
if ( if (
ts.isMethodDeclaration(referenceNode.parent) ts.isMethodDeclaration(referenceNode.parent)
@@ -365,7 +419,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
} }
function enqueueFile(filename: string): void { function enqueueFile(filename: string): void {
const sourceFile = program.getSourceFile(filename); const sourceFile = program!.getSourceFile(filename);
if (!sourceFile) { if (!sourceFile) {
console.warn(`Cannot find source file ${filename}`); console.warn(`Cannot find source file ${filename}`);
return; return;
@@ -391,7 +445,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts')); options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts'));
// Add fake usage files // Add fake usage files
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint:${index}.ts`)); options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`));
let step = 0; let step = 0;
@@ -401,7 +455,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
let node: ts.Node; let node: ts.Node;
if (step % 100 === 0) { if (step % 100 === 0) {
console.log(`${step}/${step+black_queue.length+gray_queue.length} (${black_queue.length}, ${gray_queue.length})`); console.log(`${step}/${step + black_queue.length + gray_queue.length} (${black_queue.length}, ${gray_queue.length})`);
} }
if (black_queue.length === 0) { if (black_queue.length === 0) {
@@ -418,7 +472,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
} }
if (black_queue.length > 0) { if (black_queue.length > 0) {
node = black_queue.shift(); node = black_queue.shift()!;
} else { } else {
// only gray nodes remaining... // only gray nodes remaining...
break; break;
@@ -441,7 +495,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
} }
if (options.shakeLevel === ShakeLevel.ClassMembers && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration))) { if (options.shakeLevel === ShakeLevel.ClassMembers && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration))) {
enqueue_black(declaration.name); enqueue_black(declaration.name!);
for (let j = 0; j < declaration.members.length; j++) { for (let j = 0; j < declaration.members.length; j++) {
const member = declaration.members[j]; const member = declaration.members[j];
@@ -493,6 +547,9 @@ function nodeIsInItsOwnDeclaration(nodeSourceFile: ts.SourceFile, node: ts.Node,
function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLevel): ITreeShakingResult { function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLevel): ITreeShakingResult {
const program = languageService.getProgram(); const program = languageService.getProgram();
if (!program) {
throw new Error('Could not get program from language service');
}
let result: ITreeShakingResult = {}; let result: ITreeShakingResult = {};
const writeFile = (filePath: string, contents: string): void => { const writeFile = (filePath: string, contents: string): void => {
@@ -556,12 +613,12 @@ function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLe
const leadingTriviaWidth = node.getLeadingTriviaWidth(); const leadingTriviaWidth = node.getLeadingTriviaWidth();
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth); const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
if (survivingImports.length > 0) { if (survivingImports.length > 0) {
if (node.importClause && getColor(node.importClause) === NodeColor.Black) { if (node.importClause && node.importClause.name && getColor(node.importClause) === NodeColor.Black) {
return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`); return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
} }
return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`); return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
} else { } else {
if (node.importClause && getColor(node.importClause) === NodeColor.Black) { if (node.importClause && node.importClause.name && getColor(node.importClause) === NodeColor.Black) {
return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`); return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`);
} }
} }
@@ -577,7 +634,7 @@ function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLe
let toWrite = node.getFullText(); let toWrite = node.getFullText();
for (let i = node.members.length - 1; i >= 0; i--) { for (let i = node.members.length - 1; i >= 0; i--) {
const member = node.members[i]; const member = node.members[i];
if (getColor(member) === NodeColor.Black) { if (getColor(member) === NodeColor.Black || !member.name) {
// keep method // keep method
continue; continue;
} }
@@ -625,74 +682,13 @@ function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLe
/** /**
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module) * Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
*/ */
function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol, ts.Declaration] { function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | null, ts.Declaration | null] {
/**
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
*/
/* @internal */
function getContainingObjectLiteralElement(node: ts.Node): ts.ObjectLiteralElement | undefined {
switch (node.kind) {
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.NumericLiteral:
if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) {
return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
}
// falls through
case ts.SyntaxKind.Identifier:
return ts.isObjectLiteralElement(node.parent) &&
(node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) &&
node.parent.name === node ? node.parent : undefined;
}
return undefined;
}
function getPropertySymbolsFromType(type: ts.Type, propName: ts.PropertyName) { // Use some TypeScript internals to avoid code duplication
function getTextOfPropertyName(name: ts.PropertyName): string { type ObjectLiteralElementWithName = ts.ObjectLiteralElement & { name: ts.PropertyName; parent: ts.ObjectLiteralExpression | ts.JsxAttributes };
const getPropertySymbolsFromContextualType: (node: ObjectLiteralElementWithName, checker: ts.TypeChecker, contextualType: ts.Type, unionSymbolOk: boolean) => ReadonlyArray<ts.Symbol> = (<any>ts).getPropertySymbolsFromContextualType;
function isStringOrNumericLiteral(node: ts.Node): node is ts.StringLiteral | ts.NumericLiteral { const getContainingObjectLiteralElement: (node: ts.Node) => ObjectLiteralElementWithName | undefined = (<any>ts).getContainingObjectLiteralElement;
const kind = node.kind; const getNameFromPropertyName: (name: ts.PropertyName) => string | undefined = (<any>ts).getNameFromPropertyName;
return kind === ts.SyntaxKind.StringLiteral
|| kind === ts.SyntaxKind.NumericLiteral;
}
switch (name.kind) {
case ts.SyntaxKind.Identifier:
return name.text;
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.NumericLiteral:
return name.text;
case ts.SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined!;
}
}
const name = getTextOfPropertyName(propName);
if (name && type) {
const result: ts.Symbol[] = [];
const symbol = type.getProperty(name);
if (type.flags & ts.TypeFlags.Union) {
for (const t of (<ts.UnionType>type).types) {
const symbol = t.getProperty(name);
if (symbol) {
result.push(symbol);
}
}
return result;
}
if (symbol) {
result.push(symbol);
return result;
}
}
return undefined;
}
function getPropertySymbolsFromContextualType(typeChecker: ts.TypeChecker, node: ts.ObjectLiteralElement): ts.Symbol[] {
const objectLiteral = <ts.ObjectLiteralExpression | ts.JsxAttributes>node.parent;
const contextualType = typeChecker.getContextualType(objectLiteral)!;
return getPropertySymbolsFromType(contextualType, node.name!)!;
}
// Go to the original declaration for cases: // Go to the original declaration for cases:
// //
@@ -723,8 +719,14 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol,
} }
} }
const { parent } = node;
let symbol = checker.getSymbolAtLocation(node); let symbol = checker.getSymbolAtLocation(node);
let importNode: ts.Declaration = null; let importNode: ts.Declaration | null = null;
// If this is an alias, and the request came at the declaration location
// get the aliased symbol instead. This allows for goto def on an import e.g.
// import {A, B} from "mod";
// to jump to the implementation directly.
if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
const aliased = checker.getAliasedSymbol(symbol); const aliased = checker.getAliasedSymbol(symbol);
if (aliased.declarations) { if (aliased.declarations) {
@@ -755,13 +757,21 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol,
// pr/*destination*/op1: number // pr/*destination*/op1: number
// } // }
// bar<Test>(({pr/*goto*/op1})=>{}); // bar<Test>(({pr/*goto*/op1})=>{});
if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) && if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
(node === (node.parent.propertyName || node.parent.name))) { (node === (parent.propertyName || parent.name))) {
const type = checker.getTypeAtLocation(node.parent.parent); const name = getNameFromPropertyName(node);
if (type) { const type = checker.getTypeAtLocation(parent.parent);
const propSymbols = getPropertySymbolsFromType(type, node); if (name && type) {
if (propSymbols) { if (type.isUnion()) {
symbol = propSymbols[0]; const prop = type.types[0].getProperty(name);
if (prop) {
symbol = prop;
}
} else {
const prop = type.getProperty(name);
if (prop) {
symbol = prop;
}
} }
} }
} }
@@ -776,10 +786,13 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol,
// function Foo(arg: Props) {} // function Foo(arg: Props) {}
// Foo( { pr/*1*/op1: 10, prop2: false }) // Foo( { pr/*1*/op1: 10, prop2: false })
const element = getContainingObjectLiteralElement(node); const element = getContainingObjectLiteralElement(node);
if (element && checker.getContextualType(element.parent as ts.Expression)) { if (element) {
const propertySymbols = getPropertySymbolsFromContextualType(checker, element); const contextualType = element && checker.getContextualType(element.parent);
if (propertySymbols) { if (contextualType) {
symbol = propertySymbols[0]; const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
if (propertySymbols) {
symbol = propertySymbols[0];
}
} }
} }
} }

View File

@@ -3,48 +3,30 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var path_1 = require("path"); const path_1 = require("path");
var Lint = require("tslint"); const Lint = require("tslint");
var Rule = /** @class */ (function (_super) { class Rule extends Lint.Rules.AbstractRule {
__extends(Rule, _super); apply(sourceFile) {
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.apply = function (sourceFile) {
return this.applyWithWalker(new ImportPatterns(sourceFile, this.getOptions())); return this.applyWithWalker(new ImportPatterns(sourceFile, this.getOptions()));
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var ImportPatterns = /** @class */ (function (_super) {
__extends(ImportPatterns, _super);
function ImportPatterns(file, opts) {
var _this = _super.call(this, file, opts) || this;
_this.imports = Object.create(null);
return _this;
} }
ImportPatterns.prototype.visitImportDeclaration = function (node) { }
var path = node.moduleSpecifier.getText(); exports.Rule = Rule;
class ImportPatterns extends Lint.RuleWalker {
constructor(file, opts) {
super(file, opts);
this.imports = Object.create(null);
}
visitImportDeclaration(node) {
let path = node.moduleSpecifier.getText();
// remove quotes // remove quotes
path = path.slice(1, -1); path = path.slice(1, -1);
if (path[0] === '.') { if (path[0] === '.') {
path = path_1.join(path_1.dirname(node.getSourceFile().fileName), path); path = path_1.join(path_1.dirname(node.getSourceFile().fileName), path);
} }
if (this.imports[path]) { if (this.imports[path]) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), "Duplicate imports for '" + path + "'.")); this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Duplicate imports for '${path}'.`));
} }
this.imports[path] = true; this.imports[path] = true;
}; }
return ImportPatterns; }
}(Lint.RuleWalker));

View File

@@ -3,79 +3,60 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript"); const ts = require("typescript");
var Lint = require("tslint"); const Lint = require("tslint");
var minimatch = require("minimatch"); const minimatch = require("minimatch");
var path_1 = require("path"); const path_1 = require("path");
var Rule = /** @class */ (function (_super) { class Rule extends Lint.Rules.AbstractRule {
__extends(Rule, _super); apply(sourceFile) {
function Rule() { const configs = this.getOptions().ruleArguments;
return _super !== null && _super.apply(this, arguments) || this; for (const config of configs) {
}
Rule.prototype.apply = function (sourceFile) {
var configs = this.getOptions().ruleArguments;
for (var _i = 0, configs_1 = configs; _i < configs_1.length; _i++) {
var config = configs_1[_i];
if (minimatch(sourceFile.fileName, config.target)) { if (minimatch(sourceFile.fileName, config.target)) {
return this.applyWithWalker(new ImportPatterns(sourceFile, this.getOptions(), config)); return this.applyWithWalker(new ImportPatterns(sourceFile, this.getOptions(), config));
} }
} }
return []; return [];
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var ImportPatterns = /** @class */ (function (_super) {
__extends(ImportPatterns, _super);
function ImportPatterns(file, opts, _config) {
var _this = _super.call(this, file, opts) || this;
_this._config = _config;
return _this;
} }
ImportPatterns.prototype.visitImportEqualsDeclaration = function (node) { }
exports.Rule = Rule;
class ImportPatterns extends Lint.RuleWalker {
constructor(file, opts, _config) {
super(file, opts);
this._config = _config;
}
visitImportEqualsDeclaration(node) {
if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) {
this._validateImport(node.moduleReference.expression.getText(), node); this._validateImport(node.moduleReference.expression.getText(), node);
} }
}; }
ImportPatterns.prototype.visitImportDeclaration = function (node) { visitImportDeclaration(node) {
this._validateImport(node.moduleSpecifier.getText(), node); this._validateImport(node.moduleSpecifier.getText(), node);
}; }
ImportPatterns.prototype.visitCallExpression = function (node) { visitCallExpression(node) {
_super.prototype.visitCallExpression.call(this, node); super.visitCallExpression(node);
// import('foo') statements inside the code // import('foo') statements inside the code
if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { if (node.expression.kind === ts.SyntaxKind.ImportKeyword) {
var path = node.arguments[0]; const [path] = node.arguments;
this._validateImport(path.getText(), node); this._validateImport(path.getText(), node);
} }
}; }
ImportPatterns.prototype._validateImport = function (path, node) { _validateImport(path, node) {
// remove quotes // remove quotes
path = path.slice(1, -1); path = path.slice(1, -1);
// resolve relative paths // resolve relative paths
if (path[0] === '.') { if (path[0] === '.') {
path = path_1.join(this.getSourceFile().fileName, path); path = path_1.join(this.getSourceFile().fileName, path);
} }
var restrictions; let restrictions;
if (typeof this._config.restrictions === 'string') { if (typeof this._config.restrictions === 'string') {
restrictions = [this._config.restrictions]; restrictions = [this._config.restrictions];
} }
else { else {
restrictions = this._config.restrictions; restrictions = this._config.restrictions;
} }
var matched = false; let matched = false;
for (var _i = 0, restrictions_1 = restrictions; _i < restrictions_1.length; _i++) { for (const pattern of restrictions) {
var pattern = restrictions_1[_i];
if (minimatch(path, pattern)) { if (minimatch(path, pattern)) {
matched = true; matched = true;
break; break;
@@ -83,8 +64,7 @@ var ImportPatterns = /** @class */ (function (_super) {
} }
if (!matched) { if (!matched) {
// None of the restrictions matched // None of the restrictions matched
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), "Imports violates '" + restrictions.join(' or ') + "' restrictions. See https://github.com/Microsoft/vscode/wiki/Code-Organization")); this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Imports violates '${restrictions.join(' or ')}' restrictions. See https://github.com/Microsoft/vscode/wiki/Code-Organization`));
} }
}; }
return ImportPatterns; }
}(Lint.RuleWalker));

View File

@@ -3,36 +3,22 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript"); const ts = require("typescript");
var Lint = require("tslint"); const Lint = require("tslint");
var path_1 = require("path"); const path_1 = require("path");
var Rule = /** @class */ (function (_super) { class Rule extends Lint.Rules.AbstractRule {
__extends(Rule, _super); apply(sourceFile) {
function Rule() { const parts = path_1.dirname(sourceFile.fileName).split(/\\|\//);
return _super !== null && _super.apply(this, arguments) || this; const ruleArgs = this.getOptions().ruleArguments[0];
} let config;
Rule.prototype.apply = function (sourceFile) { for (let i = parts.length - 1; i >= 0; i--) {
var parts = path_1.dirname(sourceFile.fileName).split(/\\|\//);
var ruleArgs = this.getOptions().ruleArguments[0];
var config;
for (var i = parts.length - 1; i >= 0; i--) {
if (ruleArgs[parts[i]]) { if (ruleArgs[parts[i]]) {
config = { config = {
allowed: new Set(ruleArgs[parts[i]]).add(parts[i]), allowed: new Set(ruleArgs[parts[i]]).add(parts[i]),
disallowed: new Set() disallowed: new Set()
}; };
Object.keys(ruleArgs).forEach(function (key) { Object.keys(ruleArgs).forEach(key => {
if (!config.allowed.has(key)) { if (!config.allowed.has(key)) {
config.disallowed.add(key); config.disallowed.add(key);
} }
@@ -44,58 +30,54 @@ var Rule = /** @class */ (function (_super) {
return []; return [];
} }
return this.applyWithWalker(new LayeringRule(sourceFile, config, this.getOptions())); return this.applyWithWalker(new LayeringRule(sourceFile, config, this.getOptions()));
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var LayeringRule = /** @class */ (function (_super) {
__extends(LayeringRule, _super);
function LayeringRule(file, config, opts) {
var _this = _super.call(this, file, opts) || this;
_this._config = config;
return _this;
} }
LayeringRule.prototype.visitImportEqualsDeclaration = function (node) { }
exports.Rule = Rule;
class LayeringRule extends Lint.RuleWalker {
constructor(file, config, opts) {
super(file, opts);
this._config = config;
}
visitImportEqualsDeclaration(node) {
if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) {
this._validateImport(node.moduleReference.expression.getText(), node); this._validateImport(node.moduleReference.expression.getText(), node);
} }
}; }
LayeringRule.prototype.visitImportDeclaration = function (node) { visitImportDeclaration(node) {
this._validateImport(node.moduleSpecifier.getText(), node); this._validateImport(node.moduleSpecifier.getText(), node);
}; }
LayeringRule.prototype.visitCallExpression = function (node) { visitCallExpression(node) {
_super.prototype.visitCallExpression.call(this, node); super.visitCallExpression(node);
// import('foo') statements inside the code // import('foo') statements inside the code
if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { if (node.expression.kind === ts.SyntaxKind.ImportKeyword) {
var path = node.arguments[0]; const [path] = node.arguments;
this._validateImport(path.getText(), node); this._validateImport(path.getText(), node);
} }
}; }
LayeringRule.prototype._validateImport = function (path, node) { _validateImport(path, node) {
// remove quotes // remove quotes
path = path.slice(1, -1); path = path.slice(1, -1);
if (path[0] === '.') { if (path[0] === '.') {
path = path_1.join(path_1.dirname(node.getSourceFile().fileName), path); path = path_1.join(path_1.dirname(node.getSourceFile().fileName), path);
} }
var parts = path_1.dirname(path).split(/\\|\//); const parts = path_1.dirname(path).split(/\\|\//);
for (var i = parts.length - 1; i >= 0; i--) { for (let i = parts.length - 1; i >= 0; i--) {
var part = parts[i]; const part = parts[i];
if (this._config.allowed.has(part)) { if (this._config.allowed.has(part)) {
// GOOD - same layer // GOOD - same layer
return; return;
} }
if (this._config.disallowed.has(part)) { if (this._config.disallowed.has(part)) {
// BAD - wrong layer // BAD - wrong layer
var message = "Bad layering. You are not allowed to access '" + part + "' from here, allowed layers are: [" + LayeringRule._print(this._config.allowed) + "]"; const message = `Bad layering. You are not allowed to access '${part}' from here, allowed layers are: [${LayeringRule._print(this._config.allowed)}]`;
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), message)); this.addFailure(this.createFailure(node.getStart(), node.getWidth(), message));
return; return;
} }
} }
}; }
LayeringRule._print = function (set) { static _print(set) {
var r = []; const r = [];
set.forEach(function (e) { return r.push(e); }); set.forEach(e => r.push(e));
return r.join(', '); return r.join(', ');
}; }
return LayeringRule; }
}(Lint.RuleWalker));

View File

@@ -16,9 +16,9 @@ export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const parts = dirname(sourceFile.fileName).split(/\\|\//); const parts = dirname(sourceFile.fileName).split(/\\|\//);
let ruleArgs = this.getOptions().ruleArguments[0]; const ruleArgs = this.getOptions().ruleArguments[0];
let config: Config; let config: Config | undefined;
for (let i = parts.length - 1; i >= 0; i--) { for (let i = parts.length - 1; i >= 0; i--) {
if (ruleArgs[parts[i]]) { if (ruleArgs[parts[i]]) {
config = { config = {
@@ -26,8 +26,8 @@ export class Rule extends Lint.Rules.AbstractRule {
disallowed: new Set<string>() disallowed: new Set<string>()
}; };
Object.keys(ruleArgs).forEach(key => { Object.keys(ruleArgs).forEach(key => {
if (!config.allowed.has(key)) { if (!config!.allowed.has(key)) {
config.disallowed.add(key); config!.disallowed.add(key);
} }
}); });
break; break;
@@ -98,7 +98,7 @@ class LayeringRule extends Lint.RuleWalker {
} }
static _print(set: Set<string>): string { static _print(set: Set<string>): string {
let r: string[] = []; const r: string[] = [];
set.forEach(e => r.push(e)); set.forEach(e => r.push(e));
return r.join(', '); return r.join(', ');
} }

View File

@@ -0,0 +1,22 @@
"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 });
const ts = require("typescript");
const Lint = require("tslint");
class Rule extends Lint.Rules.AbstractRule {
apply(sourceFile) {
return this.applyWithWalker(new NewBufferRuleWalker(sourceFile, this.getOptions()));
}
}
exports.Rule = Rule;
class NewBufferRuleWalker extends Lint.RuleWalker {
visitNewExpression(node) {
if (node.expression.kind === ts.SyntaxKind.Identifier && node.expression && node.expression.text === 'Buffer') {
this.addFailureAtNode(node, '`new Buffer` is deprecated. Consider Buffer.From or Buffer.alloc instead.');
}
super.visitNewExpression(node);
}
}

View File

@@ -0,0 +1,23 @@
/*---------------------------------------------------------------------------------------------
* 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 Lint from 'tslint';
export class Rule extends Lint.Rules.AbstractRule {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NewBufferRuleWalker(sourceFile, this.getOptions()));
}
}
class NewBufferRuleWalker extends Lint.RuleWalker {
visitNewExpression(node: ts.NewExpression) {
if (node.expression.kind === ts.SyntaxKind.Identifier && node.expression && (node.expression as ts.Identifier).text === 'Buffer') {
this.addFailureAtNode(node, '`new Buffer` is deprecated. Consider Buffer.From or Buffer.alloc instead.');
}
super.visitNewExpression(node);
}
}

View File

@@ -3,57 +3,42 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript"); const ts = require("typescript");
var Lint = require("tslint"); const Lint = require("tslint");
var path_1 = require("path"); const path_1 = require("path");
var Rule = /** @class */ (function (_super) { class Rule extends Lint.Rules.AbstractRule {
__extends(Rule, _super); apply(sourceFile) {
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.apply = function (sourceFile) {
if (/vs(\/|\\)editor/.test(sourceFile.fileName)) { if (/vs(\/|\\)editor/.test(sourceFile.fileName)) {
// the vs/editor folder is allowed to use the standalone editor // the vs/editor folder is allowed to use the standalone editor
return []; return [];
} }
return this.applyWithWalker(new NoStandaloneEditorRuleWalker(sourceFile, this.getOptions())); return this.applyWithWalker(new NoStandaloneEditorRuleWalker(sourceFile, this.getOptions()));
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var NoStandaloneEditorRuleWalker = /** @class */ (function (_super) {
__extends(NoStandaloneEditorRuleWalker, _super);
function NoStandaloneEditorRuleWalker(file, opts) {
return _super.call(this, file, opts) || this;
} }
NoStandaloneEditorRuleWalker.prototype.visitImportEqualsDeclaration = function (node) { }
exports.Rule = Rule;
class NoStandaloneEditorRuleWalker extends Lint.RuleWalker {
constructor(file, opts) {
super(file, opts);
}
visitImportEqualsDeclaration(node) {
if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { if (node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) {
this._validateImport(node.moduleReference.expression.getText(), node); this._validateImport(node.moduleReference.expression.getText(), node);
} }
}; }
NoStandaloneEditorRuleWalker.prototype.visitImportDeclaration = function (node) { visitImportDeclaration(node) {
this._validateImport(node.moduleSpecifier.getText(), node); this._validateImport(node.moduleSpecifier.getText(), node);
}; }
NoStandaloneEditorRuleWalker.prototype.visitCallExpression = function (node) { visitCallExpression(node) {
_super.prototype.visitCallExpression.call(this, node); super.visitCallExpression(node);
// import('foo') statements inside the code // import('foo') statements inside the code
if (node.expression.kind === ts.SyntaxKind.ImportKeyword) { if (node.expression.kind === ts.SyntaxKind.ImportKeyword) {
var path = node.arguments[0]; const [path] = node.arguments;
this._validateImport(path.getText(), node); this._validateImport(path.getText(), node);
} }
}; }
NoStandaloneEditorRuleWalker.prototype._validateImport = function (path, node) { // {{SQL CARBON EDIT}} - Rename node argument to _node to prevent errors since it is not used
_validateImport(path, _node) {
// remove quotes // remove quotes
path = path.slice(1, -1); path = path.slice(1, -1);
// resolve relative paths // resolve relative paths
@@ -68,6 +53,5 @@ var NoStandaloneEditorRuleWalker = /** @class */ (function (_super) {
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
//this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Not allowed to import standalone editor modules. See https://github.com/Microsoft/vscode/wiki/Code-Organization`)); //this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Not allowed to import standalone editor modules. See https://github.com/Microsoft/vscode/wiki/Code-Organization`));
} }
}; }
return NoStandaloneEditorRuleWalker; }
}(Lint.RuleWalker));

View File

@@ -43,7 +43,8 @@ class NoStandaloneEditorRuleWalker extends Lint.RuleWalker {
} }
} }
private _validateImport(path: string, node: ts.Node): void { // {{SQL CARBON EDIT}} - Rename node argument to _node to prevent errors since it is not used
private _validateImport(path: string, _node: ts.Node): void {
// remove quotes // remove quotes
path = path.slice(1, -1); path = path.slice(1, -1);

View File

@@ -3,32 +3,17 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript"); const ts = require("typescript");
var Lint = require("tslint"); const Lint = require("tslint");
/** /**
* Implementation of the no-unexternalized-strings rule. * Implementation of the no-unexternalized-strings rule.
*/ */
var Rule = /** @class */ (function (_super) { class Rule extends Lint.Rules.AbstractRule {
__extends(Rule, _super); apply(sourceFile) {
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.apply = function (sourceFile) {
return this.applyWithWalker(new NoUnexternalizedStringsRuleWalker(sourceFile, this.getOptions())); return this.applyWithWalker(new NoUnexternalizedStringsRuleWalker(sourceFile, this.getOptions()));
}; }
return Rule; }
}(Lint.Rules.AbstractRule));
exports.Rule = Rule; exports.Rule = Rule;
function isStringLiteral(node) { function isStringLiteral(node) {
return node && node.kind === ts.SyntaxKind.StringLiteral; return node && node.kind === ts.SyntaxKind.StringLiteral;
@@ -39,73 +24,76 @@ function isObjectLiteral(node) {
function isPropertyAssignment(node) { function isPropertyAssignment(node) {
return node && node.kind === ts.SyntaxKind.PropertyAssignment; return node && node.kind === ts.SyntaxKind.PropertyAssignment;
} }
var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) { class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
__extends(NoUnexternalizedStringsRuleWalker, _super); constructor(file, opts) {
function NoUnexternalizedStringsRuleWalker(file, opts) { super(file, opts);
var _this = _super.call(this, file, opts) || this; this.signatures = Object.create(null);
_this.signatures = Object.create(null); this.ignores = Object.create(null);
_this.ignores = Object.create(null); this.messageIndex = undefined;
_this.messageIndex = undefined; this.keyIndex = undefined;
_this.keyIndex = undefined; this.usedKeys = Object.create(null);
_this.usedKeys = Object.create(null); const options = this.getOptions();
var options = _this.getOptions(); const first = options && options.length > 0 ? options[0] : null;
var first = options && options.length > 0 ? options[0] : null;
if (first) { if (first) {
if (Array.isArray(first.signatures)) { if (Array.isArray(first.signatures)) {
first.signatures.forEach(function (signature) { return _this.signatures[signature] = true; }); first.signatures.forEach((signature) => this.signatures[signature] = true);
} }
if (Array.isArray(first.ignores)) { if (Array.isArray(first.ignores)) {
first.ignores.forEach(function (ignore) { return _this.ignores[ignore] = true; }); first.ignores.forEach((ignore) => this.ignores[ignore] = true);
} }
if (typeof first.messageIndex !== 'undefined') { if (typeof first.messageIndex !== 'undefined') {
_this.messageIndex = first.messageIndex; this.messageIndex = first.messageIndex;
} }
if (typeof first.keyIndex !== 'undefined') { if (typeof first.keyIndex !== 'undefined') {
_this.keyIndex = first.keyIndex; this.keyIndex = first.keyIndex;
} }
} }
return _this;
} }
NoUnexternalizedStringsRuleWalker.prototype.visitSourceFile = function (node) { visitSourceFile(node) {
var _this = this; super.visitSourceFile(node);
_super.prototype.visitSourceFile.call(this, node); Object.keys(this.usedKeys).forEach(key => {
Object.keys(this.usedKeys).forEach(function (key) { // Keys are quoted.
var occurrences = _this.usedKeys[key]; let identifier = key.substr(1, key.length - 2);
if (!NoUnexternalizedStringsRuleWalker.IDENTIFIER.test(identifier)) {
let occurrence = this.usedKeys[key][0];
this.addFailure(this.createFailure(occurrence.key.getStart(), occurrence.key.getWidth(), `The key ${occurrence.key.getText()} doesn't conform to a valid localize identifier`));
}
const occurrences = this.usedKeys[key];
if (occurrences.length > 1) { if (occurrences.length > 1) {
occurrences.forEach(function (occurrence) { occurrences.forEach(occurrence => {
_this.addFailure((_this.createFailure(occurrence.key.getStart(), occurrence.key.getWidth(), "Duplicate key " + occurrence.key.getText() + " with different message value."))); this.addFailure((this.createFailure(occurrence.key.getStart(), occurrence.key.getWidth(), `Duplicate key ${occurrence.key.getText()} with different message value.`)));
}); });
} }
}); });
}; }
NoUnexternalizedStringsRuleWalker.prototype.visitStringLiteral = function (node) { visitStringLiteral(node) {
this.checkStringLiteral(node); this.checkStringLiteral(node);
_super.prototype.visitStringLiteral.call(this, node); super.visitStringLiteral(node);
}; }
NoUnexternalizedStringsRuleWalker.prototype.checkStringLiteral = function (node) { checkStringLiteral(node) {
var text = node.getText(); const text = node.getText();
var doubleQuoted = text.length >= 2 && text[0] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE && text[text.length - 1] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE; const doubleQuoted = text.length >= 2 && text[0] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE && text[text.length - 1] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE;
var info = this.findDescribingParent(node); const info = this.findDescribingParent(node);
// Ignore strings in import and export nodes. // Ignore strings in import and export nodes.
if (info && info.isImport && doubleQuoted) { if (info && info.isImport && doubleQuoted) {
var fix = [ const fix = [
Lint.Replacement.replaceFromTo(node.getStart(), 1, '\''), Lint.Replacement.replaceFromTo(node.getStart(), 1, '\''),
Lint.Replacement.replaceFromTo(node.getStart() + text.length - 1, 1, '\''), Lint.Replacement.replaceFromTo(node.getStart() + text.length - 1, 1, '\''),
]; ];
this.addFailureAtNode(node, NoUnexternalizedStringsRuleWalker.ImportFailureMessage, fix); this.addFailureAtNode(node, NoUnexternalizedStringsRuleWalker.ImportFailureMessage, fix);
return; return;
} }
var callInfo = info ? info.callInfo : null; const callInfo = info ? info.callInfo : null;
var functionName = callInfo ? callInfo.callExpression.expression.getText() : null; const functionName = callInfo ? callInfo.callExpression.expression.getText() : null;
if (functionName && this.ignores[functionName]) { if (functionName && this.ignores[functionName]) {
return; return;
} }
if (doubleQuoted && (!callInfo || callInfo.argIndex === -1 || !this.signatures[functionName])) { if (doubleQuoted && (!callInfo || callInfo.argIndex === -1 || !this.signatures[functionName])) {
var s = node.getText(); const s = node.getText();
var fix = [ const fix = [
Lint.Replacement.replaceFromTo(node.getStart(), node.getWidth(), "nls.localize('KEY-" + s.substring(1, s.length - 1) + "', " + s + ")"), Lint.Replacement.replaceFromTo(node.getStart(), node.getWidth(), `nls.localize('KEY-${s.substring(1, s.length - 1)}', ${s})`),
]; ];
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), "Unexternalized string found: " + node.getText(), fix)); this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Unexternalized string found: ${node.getText()}`, fix));
return; return;
} }
// We have a single quoted string outside a localize function name. // We have a single quoted string outside a localize function name.
@@ -113,22 +101,22 @@ var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) {
return; return;
} }
// We have a string that is a direct argument into the localize call. // We have a string that is a direct argument into the localize call.
var keyArg = callInfo.argIndex === this.keyIndex const keyArg = callInfo && callInfo.argIndex === this.keyIndex
? callInfo.callExpression.arguments[this.keyIndex] ? callInfo.callExpression.arguments[this.keyIndex]
: null; : null;
if (keyArg) { if (keyArg) {
if (isStringLiteral(keyArg)) { if (isStringLiteral(keyArg)) {
this.recordKey(keyArg, this.messageIndex ? callInfo.callExpression.arguments[this.messageIndex] : undefined); this.recordKey(keyArg, this.messageIndex && callInfo ? callInfo.callExpression.arguments[this.messageIndex] : undefined);
} }
else if (isObjectLiteral(keyArg)) { else if (isObjectLiteral(keyArg)) {
for (var i = 0; i < keyArg.properties.length; i++) { for (let i = 0; i < keyArg.properties.length; i++) {
var property = keyArg.properties[i]; const property = keyArg.properties[i];
if (isPropertyAssignment(property)) { if (isPropertyAssignment(property)) {
var name_1 = property.name.getText(); const name = property.name.getText();
if (name_1 === 'key') { if (name === 'key') {
var initializer = property.initializer; const initializer = property.initializer;
if (isStringLiteral(initializer)) { if (isStringLiteral(initializer)) {
this.recordKey(initializer, this.messageIndex ? callInfo.callExpression.arguments[this.messageIndex] : undefined); this.recordKey(initializer, this.messageIndex && callInfo ? callInfo.callExpression.arguments[this.messageIndex] : undefined);
} }
break; break;
} }
@@ -136,42 +124,42 @@ var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) {
} }
} }
} }
var messageArg = callInfo.callExpression.arguments[this.messageIndex]; const messageArg = callInfo.callExpression.arguments[this.messageIndex];
if (messageArg && messageArg.kind !== ts.SyntaxKind.StringLiteral) { if (messageArg && messageArg.kind !== ts.SyntaxKind.StringLiteral) {
this.addFailure(this.createFailure(messageArg.getStart(), messageArg.getWidth(), "Message argument to '" + callInfo.callExpression.expression.getText() + "' must be a string literal.")); this.addFailure(this.createFailure(messageArg.getStart(), messageArg.getWidth(), `Message argument to '${callInfo.callExpression.expression.getText()}' must be a string literal.`));
return; return;
} }
}; }
NoUnexternalizedStringsRuleWalker.prototype.recordKey = function (keyNode, messageNode) { recordKey(keyNode, messageNode) {
var text = keyNode.getText(); const text = keyNode.getText();
// We have an empty key // We have an empty key
if (text.match(/(['"]) *\1/)) { if (text.match(/(['"]) *\1/)) {
if (messageNode) { if (messageNode) {
this.addFailureAtNode(keyNode, "Key is empty for message: " + messageNode.getText()); this.addFailureAtNode(keyNode, `Key is empty for message: ${messageNode.getText()}`);
} }
else { else {
this.addFailureAtNode(keyNode, "Key is empty."); this.addFailureAtNode(keyNode, `Key is empty.`);
} }
return; return;
} }
var occurrences = this.usedKeys[text]; let occurrences = this.usedKeys[text];
if (!occurrences) { if (!occurrences) {
occurrences = []; occurrences = [];
this.usedKeys[text] = occurrences; this.usedKeys[text] = occurrences;
} }
if (messageNode) { if (messageNode) {
if (occurrences.some(function (pair) { return pair.message ? pair.message.getText() === messageNode.getText() : false; })) { if (occurrences.some(pair => pair.message ? pair.message.getText() === messageNode.getText() : false)) {
return; return;
} }
} }
occurrences.push({ key: keyNode, message: messageNode }); occurrences.push({ key: keyNode, message: messageNode });
}; }
NoUnexternalizedStringsRuleWalker.prototype.findDescribingParent = function (node) { findDescribingParent(node) {
var parent; let parent;
while ((parent = node.parent)) { while ((parent = node.parent)) {
var kind = parent.kind; const kind = parent.kind;
if (kind === ts.SyntaxKind.CallExpression) { if (kind === ts.SyntaxKind.CallExpression) {
var callExpression = parent; const callExpression = parent;
return { callInfo: { callExpression: callExpression, argIndex: callExpression.arguments.indexOf(node) } }; return { callInfo: { callExpression: callExpression, argIndex: callExpression.arguments.indexOf(node) } };
} }
else if (kind === ts.SyntaxKind.ImportEqualsDeclaration || kind === ts.SyntaxKind.ImportDeclaration || kind === ts.SyntaxKind.ExportDeclaration) { else if (kind === ts.SyntaxKind.ImportEqualsDeclaration || kind === ts.SyntaxKind.ImportDeclaration || kind === ts.SyntaxKind.ExportDeclaration) {
@@ -185,8 +173,9 @@ var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) {
} }
node = parent; node = parent;
} }
}; return null;
NoUnexternalizedStringsRuleWalker.ImportFailureMessage = 'Do not use double quotes for imports.'; }
NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE = '"'; }
return NoUnexternalizedStringsRuleWalker; NoUnexternalizedStringsRuleWalker.ImportFailureMessage = 'Do not use double quotes for imports.';
}(Lint.RuleWalker)); NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE = '"';
NoUnexternalizedStringsRuleWalker.IDENTIFIER = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/;

View File

@@ -40,7 +40,7 @@ function isPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment {
interface KeyMessagePair { interface KeyMessagePair {
key: ts.StringLiteral; key: ts.StringLiteral;
message: ts.Node; message: ts.Node | undefined;
} }
class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker { class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
@@ -50,8 +50,8 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
private static DOUBLE_QUOTE: string = '"'; private static DOUBLE_QUOTE: string = '"';
private signatures: Map<boolean>; private signatures: Map<boolean>;
private messageIndex: number; private messageIndex: number | undefined;
private keyIndex: number; private keyIndex: number | undefined;
private ignores: Map<boolean>; private ignores: Map<boolean>;
private usedKeys: Map<KeyMessagePair[]>; private usedKeys: Map<KeyMessagePair[]>;
@@ -63,8 +63,8 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
this.messageIndex = undefined; this.messageIndex = undefined;
this.keyIndex = undefined; this.keyIndex = undefined;
this.usedKeys = Object.create(null); this.usedKeys = Object.create(null);
let options: any[] = this.getOptions(); const options: any[] = this.getOptions();
let first: UnexternalizedStringsOptions = options && options.length > 0 ? options[0] : null; const first: UnexternalizedStringsOptions = options && options.length > 0 ? options[0] : null;
if (first) { if (first) {
if (Array.isArray(first.signatures)) { if (Array.isArray(first.signatures)) {
first.signatures.forEach((signature: string) => this.signatures[signature] = true); first.signatures.forEach((signature: string) => this.signatures[signature] = true);
@@ -81,10 +81,17 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
} }
} }
private static IDENTIFIER = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/;
protected visitSourceFile(node: ts.SourceFile): void { protected visitSourceFile(node: ts.SourceFile): void {
super.visitSourceFile(node); super.visitSourceFile(node);
Object.keys(this.usedKeys).forEach(key => { Object.keys(this.usedKeys).forEach(key => {
let occurrences = this.usedKeys[key]; // Keys are quoted.
let identifier = key.substr(1, key.length - 2);
if (!NoUnexternalizedStringsRuleWalker.IDENTIFIER.test(identifier)) {
let occurrence = this.usedKeys[key][0];
this.addFailure(this.createFailure(occurrence.key.getStart(), occurrence.key.getWidth(), `The key ${occurrence.key.getText()} doesn't conform to a valid localize identifier`));
}
const occurrences = this.usedKeys[key];
if (occurrences.length > 1) { if (occurrences.length > 1) {
occurrences.forEach(occurrence => { occurrences.forEach(occurrence => {
this.addFailure((this.createFailure(occurrence.key.getStart(), occurrence.key.getWidth(), `Duplicate key ${occurrence.key.getText()} with different message value.`))); this.addFailure((this.createFailure(occurrence.key.getStart(), occurrence.key.getWidth(), `Duplicate key ${occurrence.key.getText()} with different message value.`)));
@@ -99,9 +106,9 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
} }
private checkStringLiteral(node: ts.StringLiteral): void { private checkStringLiteral(node: ts.StringLiteral): void {
let text = node.getText(); const text = node.getText();
let doubleQuoted = text.length >= 2 && text[0] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE && text[text.length - 1] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE; const doubleQuoted = text.length >= 2 && text[0] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE && text[text.length - 1] === NoUnexternalizedStringsRuleWalker.DOUBLE_QUOTE;
let info = this.findDescribingParent(node); const info = this.findDescribingParent(node);
// Ignore strings in import and export nodes. // Ignore strings in import and export nodes.
if (info && info.isImport && doubleQuoted) { if (info && info.isImport && doubleQuoted) {
const fix = [ const fix = [
@@ -115,13 +122,13 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
); );
return; return;
} }
let callInfo = info ? info.callInfo : null; const callInfo = info ? info.callInfo : null;
let functionName = callInfo ? callInfo.callExpression.expression.getText() : null; const functionName = callInfo ? callInfo.callExpression.expression.getText() : null;
if (functionName && this.ignores[functionName]) { if (functionName && this.ignores[functionName]) {
return; return;
} }
if (doubleQuoted && (!callInfo || callInfo.argIndex === -1 || !this.signatures[functionName])) { if (doubleQuoted && (!callInfo || callInfo.argIndex === -1 || !this.signatures[functionName!])) {
const s = node.getText(); const s = node.getText();
const fix = [ const fix = [
Lint.Replacement.replaceFromTo(node.getStart(), node.getWidth(), `nls.localize('KEY-${s.substring(1, s.length - 1)}', ${s})`), Lint.Replacement.replaceFromTo(node.getStart(), node.getWidth(), `nls.localize('KEY-${s.substring(1, s.length - 1)}', ${s})`),
@@ -130,25 +137,25 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
return; return;
} }
// We have a single quoted string outside a localize function name. // We have a single quoted string outside a localize function name.
if (!doubleQuoted && !this.signatures[functionName]) { if (!doubleQuoted && !this.signatures[functionName!]) {
return; return;
} }
// We have a string that is a direct argument into the localize call. // We have a string that is a direct argument into the localize call.
let keyArg: ts.Expression = callInfo.argIndex === this.keyIndex const keyArg: ts.Expression | null = callInfo && callInfo.argIndex === this.keyIndex
? callInfo.callExpression.arguments[this.keyIndex] ? callInfo.callExpression.arguments[this.keyIndex]
: null; : null;
if (keyArg) { if (keyArg) {
if (isStringLiteral(keyArg)) { if (isStringLiteral(keyArg)) {
this.recordKey(keyArg, this.messageIndex ? callInfo.callExpression.arguments[this.messageIndex] : undefined); this.recordKey(keyArg, this.messageIndex && callInfo ? callInfo.callExpression.arguments[this.messageIndex] : undefined);
} else if (isObjectLiteral(keyArg)) { } else if (isObjectLiteral(keyArg)) {
for (let i = 0; i < keyArg.properties.length; i++) { for (let i = 0; i < keyArg.properties.length; i++) {
let property = keyArg.properties[i]; const property = keyArg.properties[i];
if (isPropertyAssignment(property)) { if (isPropertyAssignment(property)) {
let name = property.name.getText(); const name = property.name.getText();
if (name === 'key') { if (name === 'key') {
let initializer = property.initializer; const initializer = property.initializer;
if (isStringLiteral(initializer)) { if (isStringLiteral(initializer)) {
this.recordKey(initializer, this.messageIndex ? callInfo.callExpression.arguments[this.messageIndex] : undefined); this.recordKey(initializer, this.messageIndex && callInfo ? callInfo.callExpression.arguments[this.messageIndex] : undefined);
} }
break; break;
} }
@@ -157,18 +164,18 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
} }
} }
const messageArg = callInfo.callExpression.arguments[this.messageIndex]; const messageArg = callInfo!.callExpression.arguments[this.messageIndex!];
if (messageArg && messageArg.kind !== ts.SyntaxKind.StringLiteral) { if (messageArg && messageArg.kind !== ts.SyntaxKind.StringLiteral) {
this.addFailure(this.createFailure( this.addFailure(this.createFailure(
messageArg.getStart(), messageArg.getWidth(), messageArg.getStart(), messageArg.getWidth(),
`Message argument to '${callInfo.callExpression.expression.getText()}' must be a string literal.`)); `Message argument to '${callInfo!.callExpression.expression.getText()}' must be a string literal.`));
return; return;
} }
} }
private recordKey(keyNode: ts.StringLiteral, messageNode: ts.Node) { private recordKey(keyNode: ts.StringLiteral, messageNode: ts.Node | undefined) {
let text = keyNode.getText(); const text = keyNode.getText();
// We have an empty key // We have an empty key
if (text.match(/(['"]) *\1/)) { if (text.match(/(['"]) *\1/)) {
if (messageNode) { if (messageNode) {
@@ -191,12 +198,12 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
occurrences.push({ key: keyNode, message: messageNode }); occurrences.push({ key: keyNode, message: messageNode });
} }
private findDescribingParent(node: ts.Node): { callInfo?: { callExpression: ts.CallExpression, argIndex: number }, isImport?: boolean; } { private findDescribingParent(node: ts.Node): { callInfo?: { callExpression: ts.CallExpression, argIndex: number }, isImport?: boolean; } | null {
let parent: ts.Node; let parent: ts.Node;
while ((parent = node.parent)) { while ((parent = node.parent)) {
let kind = parent.kind; const kind = parent.kind;
if (kind === ts.SyntaxKind.CallExpression) { if (kind === ts.SyntaxKind.CallExpression) {
let callExpression = parent as ts.CallExpression; const callExpression = parent as ts.CallExpression;
return { callInfo: { callExpression: callExpression, argIndex: callExpression.arguments.indexOf(<any>node) } }; return { callInfo: { callExpression: callExpression, argIndex: callExpression.arguments.indexOf(<any>node) } };
} else if (kind === ts.SyntaxKind.ImportEqualsDeclaration || kind === ts.SyntaxKind.ImportDeclaration || kind === ts.SyntaxKind.ExportDeclaration) { } else if (kind === ts.SyntaxKind.ImportEqualsDeclaration || kind === ts.SyntaxKind.ImportDeclaration || kind === ts.SyntaxKind.ExportDeclaration) {
return { isImport: true }; return { isImport: true };
@@ -208,5 +215,6 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
} }
node = parent; node = parent;
} }
return null;
} }
} }

View File

@@ -3,59 +3,43 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
var Lint = require("tslint"); const Lint = require("tslint");
var fs = require("fs"); const fs = require("fs");
var Rule = /** @class */ (function (_super) { class Rule extends Lint.Rules.AbstractRule {
__extends(Rule, _super); apply(sourceFile) {
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.apply = function (sourceFile) {
return this.applyWithWalker(new TranslationRemindRuleWalker(sourceFile, this.getOptions())); return this.applyWithWalker(new TranslationRemindRuleWalker(sourceFile, this.getOptions()));
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
var TranslationRemindRuleWalker = /** @class */ (function (_super) {
__extends(TranslationRemindRuleWalker, _super);
function TranslationRemindRuleWalker(file, opts) {
return _super.call(this, file, opts) || this;
} }
TranslationRemindRuleWalker.prototype.visitImportDeclaration = function (node) { }
var declaration = node.moduleSpecifier.getText(); exports.Rule = Rule;
if (declaration !== "'" + TranslationRemindRuleWalker.NLS_MODULE + "'") { class TranslationRemindRuleWalker extends Lint.RuleWalker {
constructor(file, opts) {
super(file, opts);
}
visitImportDeclaration(node) {
const declaration = node.moduleSpecifier.getText();
if (declaration !== `'${TranslationRemindRuleWalker.NLS_MODULE}'`) {
return; return;
} }
this.visitImportLikeDeclaration(node); this.visitImportLikeDeclaration(node);
}; }
TranslationRemindRuleWalker.prototype.visitImportEqualsDeclaration = function (node) { visitImportEqualsDeclaration(node) {
var reference = node.moduleReference.getText(); const reference = node.moduleReference.getText();
if (reference !== "require('" + TranslationRemindRuleWalker.NLS_MODULE + "')") { if (reference !== `require('${TranslationRemindRuleWalker.NLS_MODULE}')`) {
return; return;
} }
this.visitImportLikeDeclaration(node); this.visitImportLikeDeclaration(node);
}; }
TranslationRemindRuleWalker.prototype.visitImportLikeDeclaration = function (node) { visitImportLikeDeclaration(node) {
var currentFile = node.getSourceFile().fileName; const currentFile = node.getSourceFile().fileName;
var matchService = currentFile.match(/vs\/workbench\/services\/\w+/); const matchService = currentFile.match(/vs\/workbench\/services\/\w+/);
var matchPart = currentFile.match(/vs\/workbench\/parts\/\w+/); const matchPart = currentFile.match(/vs\/workbench\/parts\/\w+/);
if (!matchService && !matchPart) { if (!matchService && !matchPart) {
return; return;
} }
var resource = matchService ? matchService[0] : matchPart[0]; const resource = matchService ? matchService[0] : matchPart[0];
var resourceDefined = false; let resourceDefined = false;
var json; let json;
try { try {
json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'); json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8');
} }
@@ -63,17 +47,16 @@ var TranslationRemindRuleWalker = /** @class */ (function (_super) {
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.'); 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; return;
} }
var workbenchResources = JSON.parse(json).workbench; const workbenchResources = JSON.parse(json).workbench;
workbenchResources.forEach(function (existingResource) { workbenchResources.forEach((existingResource) => {
if (existingResource.name === resource) { if (existingResource.name === resource) {
resourceDefined = true; resourceDefined = true;
return; return;
} }
}); });
if (!resourceDefined) { if (!resourceDefined) {
this.addFailureAtNode(node, "Please add '" + resource + "' to ./build/lib/i18n.resources.json file to use translations here."); this.addFailureAtNode(node, `Please add '${resource}' to ./build/lib/i18n.resources.json file to use translations here.`);
} }
}; }
TranslationRemindRuleWalker.NLS_MODULE = 'vs/nls'; }
return TranslationRemindRuleWalker; TranslationRemindRuleWalker.NLS_MODULE = 'vs/nls';
}(Lint.RuleWalker));

View File

@@ -30,7 +30,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker {
this.visitImportLikeDeclaration(node); this.visitImportLikeDeclaration(node);
} }
protected visitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration): void { protected visitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration): void {
const reference = node.moduleReference.getText(); const reference = node.moduleReference.getText();
if (reference !== `require('${TranslationRemindRuleWalker.NLS_MODULE}')`) { if (reference !== `require('${TranslationRemindRuleWalker.NLS_MODULE}')`) {
return; return;
@@ -47,7 +47,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker {
return; return;
} }
const resource = matchService ? matchService[0] : matchPart[0]; const resource = matchService ? matchService[0] : matchPart![0];
let resourceDefined = false; let resourceDefined = false;
let json; let json;
@@ -59,7 +59,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker {
} }
const workbenchResources = JSON.parse(json).workbench; const workbenchResources = JSON.parse(json).workbench;
workbenchResources.forEach(existingResource => { workbenchResources.forEach((existingResource: any) => {
if (existingResource.name === resource) { if (existingResource.name === resource) {
resourceDefined = true; resourceDefined = true;
return; return;

View File

@@ -1,10 +0,0 @@
// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
// All OSS in this folder is development time only
[{
"name": "definitelytyped",
"repositoryURL": "https://github.com/DefinitelyTyped/DefinitelyTyped",
"license": "MIT",
"isDev": true
}
]

View File

@@ -1,361 +0,0 @@
// Type definitions for Q
// Project: https://github.com/kriskowal/q
// Definitions by: Barrie Nemetchek <https://github.com/bnemetchek>, Andrew Gaspar <https://github.com/AndrewGaspar/>, John Reilly <https://github.com/johnnyreilly>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/**
* If value is a Q promise, returns the promise.
* If value is a promise from another library it is coerced into a Q promise (where possible).
*/
declare function Q<T>(promise: Q.IPromise<T>): Q.Promise<T>;
/**
* If value is not a promise, returns a promise that is fulfilled with value.
*/
declare function Q<T>(value: T): Q.Promise<T>;
/**
* Calling with nothing at all creates a void promise
*/
declare function Q(): Q.Promise<void>;
declare namespace Q {
type IWhenable<T> = IPromise<T> | T;
interface IPromise<T> {
then<U>(onFulfill?: (value: T) => IWhenable<U>, onReject?: (error: any) => IWhenable<U>): IPromise<U>;
}
interface Deferred<T> {
promise: Promise<T>;
resolve(value?: IWhenable<T>): void;
reject(reason: any): void;
notify(value: any): void;
makeNodeResolver(): (reason: any, value: T) => void;
}
interface Promise<T> {
/**
* Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object.
* finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished.
*/
fin(finallyCallback: () => any): Promise<T>;
/**
* Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object.
* finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished.
*/
finally(finallyCallback: () => any): Promise<T>;
/**
* The then method from the Promises/A+ specification, with an additional progress handler.
*/
then<U>(onFulfill?: (value: T) => IWhenable<U>, onReject?: (error: any) => IWhenable<U>, onProgress?: Function): Promise<U>;
/**
* Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason.
*
* This is especially useful in conjunction with all
*/
spread<U>(onFulfill: (...args: any[]) => IWhenable<U>, onReject?: (reason: any) => IWhenable<U>): Promise<U>;
fail<U>(onRejected: (reason: any) => IWhenable<U>): Promise<U>;
/**
* A sugar method, equivalent to promise.then(undefined, onRejected).
*/
catch<U>(onRejected: (reason: any) => IWhenable<U>): Promise<U>;
/**
* A sugar method, equivalent to promise.then(undefined, undefined, onProgress).
*/
progress(onProgress: (progress: any) => any): Promise<T>;
/**
* Much like then, but with different behavior around unhandled rejection. If there is an unhandled rejection, either because promise is rejected and no onRejected callback was provided, or because onFulfilled or onRejected threw an error or returned a rejected promise, the resulting rejection reason is thrown as an exception in a future turn of the event loop.
*
* This method should be used to terminate chains of promises that will not be passed elsewhere. Since exceptions thrown in then callbacks are consumed and transformed into rejections, exceptions at the end of the chain are easy to accidentally, silently ignore. By arranging for the exception to be thrown in a future turn of the event loop, so that it won't be caught, it causes an onerror event on the browser window, or an uncaughtException event on Node.js's process object.
*
* Exceptions thrown by done will have long stack traces, if Q.longStackSupport is set to true. If Q.onerror is set, exceptions will be delivered there instead of thrown in a future turn.
*
* The Golden Rule of done vs. then usage is: either return your promise to someone else, or if the chain ends with you, call done to terminate it.
*/
done(onFulfilled?: (value: T) => any, onRejected?: (reason: any) => any, onProgress?: (progress: any) => any): void;
/**
* If callback is a function, assumes it's a Node.js-style callback, and calls it as either callback(rejectionReason) when/if promise becomes rejected, or as callback(null, fulfillmentValue) when/if promise becomes fulfilled. If callback is not a function, simply returns promise.
*/
nodeify(callback: (reason: any, value: any) => void): Promise<T>;
/**
* Returns a promise to get the named property of an object. Essentially equivalent to
*
* promise.then(function (o) {
* return o[propertyName];
* });
*/
get<U>(propertyName: String): Promise<U>;
set<U>(propertyName: String, value: any): Promise<U>;
delete<U>(propertyName: String): Promise<U>;
/**
* Returns a promise for the result of calling the named method of an object with the given array of arguments. The object itself is this in the function, just like a synchronous method call. Essentially equivalent to
*
* promise.then(function (o) {
* return o[methodName].apply(o, args);
* });
*/
post<U>(methodName: String, args: any[]): Promise<U>;
/**
* Returns a promise for the result of calling the named method of an object with the given variadic arguments. The object itself is this in the function, just like a synchronous method call.
*/
invoke<U>(methodName: String, ...args: any[]): Promise<U>;
fapply<U>(args: any[]): Promise<U>;
fcall<U>(...args: any[]): Promise<U>;
/**
* Returns a promise for an array of the property names of an object. Essentially equivalent to
*
* promise.then(function (o) {
* return Object.keys(o);
* });
*/
keys(): Promise<string[]>;
/**
* A sugar method, equivalent to promise.then(function () { return value; }).
*/
thenResolve<U>(value: U): Promise<U>;
/**
* A sugar method, equivalent to promise.then(function () { throw reason; }).
*/
thenReject(reason: any): Promise<T>;
/**
* Attaches a handler that will observe the value of the promise when it becomes fulfilled, returning a promise for that same value, perhaps deferred but not replaced by the promise returned by the onFulfilled handler.
*/
tap(onFulfilled: (value: T) => any): Promise<T>;
timeout(ms: number, message?: string): Promise<T>;
/**
* Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed.
*/
delay(ms: number): Promise<T>;
/**
* Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true.
*/
isFulfilled(): boolean;
/**
* Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false.
*/
isRejected(): boolean;
/**
* Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false.
*/
isPending(): boolean;
valueOf(): any;
/**
* Returns a "state snapshot" object, which will be in one of three forms:
*
* - { state: "pending" }
* - { state: "fulfilled", value: <fulfllment value> }
* - { state: "rejected", reason: <rejection reason> }
*/
inspect(): PromiseState<T>;
}
interface PromiseState<T> {
/**
* "fulfilled", "rejected", "pending"
*/
state: string;
value?: T;
reason?: any;
}
// If no value provided, returned promise will be of void type
export function when(): Promise<void>;
// if no fulfill, reject, or progress provided, returned promise will be of same type
export function when<T>(value: IWhenable<T>): Promise<T>;
// If a non-promise value is provided, it will not reject or progress
export function when<T, U>(value: IWhenable<T>, onFulfilled: (val: T) => IWhenable<U>, onRejected?: (reason: any) => IWhenable<U>, onProgress?: (progress: any) => any): Promise<U>;
/**
* Currently "impossible" (and I use the term loosely) to implement due to TypeScript limitations as it is now.
* See: https://github.com/Microsoft/TypeScript/issues/1784 for discussion on it.
*/
// export function try(method: Function, ...args: any[]): Promise<any>;
export function fbind<T>(method: (...args: any[]) => IWhenable<T>, ...args: any[]): (...args: any[]) => Promise<T>;
export function fcall<T>(method: (...args: any[]) => T, ...args: any[]): Promise<T>;
export function send<T>(obj: any, functionName: string, ...args: any[]): Promise<T>;
export function invoke<T>(obj: any, functionName: string, ...args: any[]): Promise<T>;
export function mcall<T>(obj: any, functionName: string, ...args: any[]): Promise<T>;
export function denodeify<T>(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise<T>;
export function nbind<T>(nodeFunction: Function, thisArg: any, ...args: any[]): (...args: any[]) => Promise<T>;
export function nfbind<T>(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise<T>;
export function nfcall<T>(nodeFunction: Function, ...args: any[]): Promise<T>;
export function nfapply<T>(nodeFunction: Function, args: any[]): Promise<T>;
export function ninvoke<T>(nodeModule: any, functionName: string, ...args: any[]): Promise<T>;
export function npost<T>(nodeModule: any, functionName: string, args: any[]): Promise<T>;
export function nsend<T>(nodeModule: any, functionName: string, ...args: any[]): Promise<T>;
export function nmcall<T>(nodeModule: any, functionName: string, ...args: any[]): Promise<T>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<A, B, C, D, E, F>(promises: IWhenable<[IWhenable<A>, IWhenable<B>, IWhenable<C>, IWhenable<D>, IWhenable<E>, IWhenable<F>]>): Promise<[A, B, C, D, E, F]>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<A, B, C, D, E>(promises: IWhenable<[IWhenable<A>, IWhenable<B>, IWhenable<C>, IWhenable<D>, IWhenable<E>]>): Promise<[A, B, C, D, E]>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<A, B, C, D>(promises: IWhenable<[IWhenable<A>, IWhenable<B>, IWhenable<C>, IWhenable<D>]>): Promise<[A, B, C, D]>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<A, B, C>(promises: IWhenable<[IWhenable<A>, IWhenable<B>, IWhenable<C>]>): Promise<[A, B, C]>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<A, B>(promises: IWhenable<[IWhenable<A>, IWhenable<B>]>): Promise<[A, B]>;
/**
* Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.
*/
export function all<T>(promises: IWhenable<IWhenable<T>[]>): Promise<T[]>;
/**
* Returns a promise for the first of an array of promises to become settled.
*/
export function race<T>(promises: IWhenable<T>[]): Promise<T>;
/**
* Returns a promise that is fulfilled with an array of promise state snapshots, but only after all the original promises have settled, i.e. become either fulfilled or rejected.
*/
export function allSettled<T>(promises: IWhenable<IWhenable<T>[]>): Promise<PromiseState<T>[]>;
export function allResolved<T>(promises: IWhenable<IWhenable<T>[]>): Promise<Promise<T>[]>;
/**
* Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason.
* This is especially useful in conjunction with all.
*/
export function spread<T, U>(promises: IWhenable<T>[], onFulfilled: (...args: T[]) => IWhenable<U>, onRejected?: (reason: any) => IWhenable<U>): Promise<U>;
/**
* Returns a promise that will have the same result as promise, except that if promise is not fulfilled or rejected before ms milliseconds, the returned promise will be rejected with an Error with the given message. If message is not supplied, the message will be "Timed out after " + ms + " ms".
*/
export function timeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
/**
* Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed.
*/
export function delay<T>(promise: Promise<T>, ms: number): Promise<T>;
/**
* Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed.
*/
export function delay<T>(value: T, ms: number): Promise<T>;
/**
* Returns a promise that will be fulfilled with undefined after at least ms milliseconds have passed.
*/
export function delay(ms: number): Promise <void>;
/**
* Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true.
*/
export function isFulfilled(promise: Promise<any>): boolean;
/**
* Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false.
*/
export function isRejected(promise: Promise<any>): boolean;
/**
* Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false.
*/
export function isPending(promise: Promise<any>): boolean;
/**
* Returns a "deferred" object with a:
* promise property
* resolve(value) method
* reject(reason) method
* notify(value) method
* makeNodeResolver() method
*/
export function defer<T>(): Deferred<T>;
/**
* Returns a promise that is rejected with reason.
*/
export function reject<T>(reason?: any): Promise<T>;
export function Promise<T>(resolver: (resolve: (val: IWhenable<T>) => void , reject: (reason: any) => void , notify: (progress: any) => void ) => void ): Promise<T>;
/**
* Creates a new version of func that accepts any combination of promise and non-promise values, converting them to their fulfillment values before calling the original func. The returned version also always returns a promise: if func does a return or throw, then Q.promised(func) will return fulfilled or rejected promise, respectively.
*
* This can be useful for creating functions that accept either promises or non-promise values, and for ensuring that the function always returns a promise even in the face of unintentional thrown exceptions.
*/
export function promised<T>(callback: (...args: any[]) => T): (...args: any[]) => Promise<T>;
/**
* Returns whether the given value is a Q promise.
*/
export function isPromise(object: any): boolean;
/**
* Returns whether the given value is a promise (i.e. it's an object with a then function).
*/
export function isPromiseAlike(object: any): boolean;
/**
* Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false.
*/
export function isPending(object: any): boolean;
/**
* If an object is not a promise, it is as "near" as possible.
* If a promise is rejected, it is as "near" as possible too.
* If its a fulfilled promise, the fulfillment value is nearer.
* If its a deferred promise and the deferred has been resolved, the
* resolution is "nearer".
*/
export function nearer<T>(promise: Promise<T>): T;
/**
* This is an experimental tool for converting a generator function into a deferred function. This has the potential of reducing nested callbacks in engines that support yield.
*/
export function async<T>(generatorFunction: any): (...args: any[]) => Promise<T>;
export function nextTick(callback: Function): void;
/**
* A settable property that will intercept any uncaught errors that would otherwise be thrown in the next tick of the event loop, usually as a result of done. Can be useful for getting the full stack trace of an error in browsers, which is not usually possible with window.onerror.
*/
export var onerror: (reason: any) => void;
/**
* A settable property that lets you turn on long stack trace support. If turned on, "stack jumps" will be tracked across asynchronous promise operations, so that if an uncaught error is thrown by done or a rejection reason's stack property is inspected in a rejection callback, a long stack trace is produced.
*/
export var longStackSupport: boolean;
/**
* Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does).
* Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason.
* Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value.
* Calling resolve with a non-promise value causes promise to be fulfilled with that value.
*/
export function resolve<T>(object: IWhenable<T>): Promise<T>;
/**
* Resets the global "Q" variable to the value it has before Q was loaded.
* This will either be undefined if there was no version or the version of Q which was already loaded before.
* @returns { The last version of Q. }
*/
export function noConflict(): typeof Q;
}
declare module "q" {
export = Q;
}

View File

@@ -0,0 +1,16 @@
{
"registrations": [
{
"component": {
"type": "git",
"git": {
"name": "definitelytyped",
"repositoryUrl": "https://github.com/DefinitelyTyped/DefinitelyTyped",
"commitHash": "69e3ac6bec3008271f76bbfa7cf69aa9198c4ff0"
}
},
"license": "MIT"
}
],
"version": 1
}

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